From f0643b298fd83f41d39ea2496f8c93d847d07d73 Mon Sep 17 00:00:00 2001 From: "Vincent Jiang(Azure Dev)" Date: Fri, 24 Apr 2015 14:46:42 +0800 Subject: [PATCH] [XSCL C++]Azure Storage Client Library for c++ v1.0 --- BreakingChanges.txt | 4 + Changelog.txt | 17 + Microsoft.WindowsAzure.Storage.autopkg | 4 +- Microsoft.WindowsAzure.Storage.sln | 16 - Microsoft.WindowsAzure.Storage.v120.sln | 18 +- Microsoft.WindowsAzure.Storage/CMakeLists.txt | 4 +- ...icrosoft.WindowsAzure.Storage.v120.vcxproj | 2 +- .../includes/was/blob.h | 519 +++++++++++------- .../includes/was/common.h | 281 ++++++++-- .../includes/was/core.h | 56 +- .../includes/was/error_code_strings.h | 86 +-- .../includes/was/queue.h | 156 ++---- .../includes/was/service_client.h | 6 +- .../includes/was/storage_account.h | 6 +- .../includes/was/table.h | 282 +++------- .../includes/wascore/constants.h | 4 +- .../BlobsGettingStarted/Application.cpp | 19 +- ...e.Storage.BlobsGettingStarted.v120.vcxproj | 2 +- .../NativeClientLibraryDemo1.vcxproj | 10 +- .../Channel9GoingNativeDemo1/packages.config | 4 +- .../NativeClientLibraryDemo2.cpp | 5 +- .../NativeClientLibraryDemo2.sln | 2 +- .../NativeClientLibraryDemo2.vcxproj | 10 +- .../Channel9GoingNativeDemo2/packages.config | 4 +- ...ure.Storage.JsonPayloadFormat.v120.vcxproj | 2 +- ....Storage.QueuesGettingStarted.v120.vcxproj | 2 +- .../samples/SamplesCommon/packages.config | 5 - ....Storage.TablesGettingStarted.v120.vcxproj | 2 +- .../src/cloud_blob.cpp | 2 +- .../src/cloud_blob_client.cpp | 50 +- .../src/cloud_blob_container.cpp | 40 +- .../src/cloud_blob_directory.cpp | 7 +- .../src/cloud_queue_client.cpp | 16 +- .../src/cloud_table.cpp | 16 +- .../src/cloud_table_client.cpp | 16 +- .../src/hash_windows.cpp | 223 -------- .../src/logging_windows.cpp | 90 --- .../src/queue_request_factory.cpp | 2 +- .../src/util_windows.cpp | 62 --- .../tests/CMakeLists.txt | 2 + ...indowsAzure.Storage.UnitTests.v120.vcxproj | 9 +- ...ure.Storage.UnitTests.v120.vcxproj.filters | 9 +- ...oft.WindowsAzure.Storage.UnitTests.vcxproj | 7 +- ...owsAzure.Storage.UnitTests.vcxproj.filters | 9 +- .../tests/README.md | 2 +- .../tests/check_macros.h | 24 + .../tests/cloud_blob_client_test.cpp | 83 +-- .../tests/cloud_blob_container_test.cpp | 19 +- .../tests/cloud_blob_directory_test.cpp | 38 +- .../tests/cloud_blob_test.cpp | 11 +- .../tests/cloud_queue_client_test.cpp | 50 +- .../tests/cloud_storage_account_test.cpp | 142 ++++- .../tests/cloud_table_client_test.cpp | 52 +- .../tests/cloud_table_test.cpp | 15 +- .../tests/result_iterator_test.cpp | 222 ++++++++ .../tests/retry_policy_test.cpp | 16 + .../tests/unicode_test.cpp | 73 +++ Microsoft.WindowsAzure.Storage/version.rc | Bin 4548 -> 4548 bytes README.md | 4 +- packages/repositories.config | 2 + 60 files changed, 1626 insertions(+), 1215 deletions(-) delete mode 100644 Microsoft.WindowsAzure.Storage/samples/SamplesCommon/packages.config delete mode 100644 Microsoft.WindowsAzure.Storage/src/hash_windows.cpp delete mode 100644 Microsoft.WindowsAzure.Storage/src/logging_windows.cpp delete mode 100644 Microsoft.WindowsAzure.Storage/src/util_windows.cpp create mode 100644 Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp create mode 100644 Microsoft.WindowsAzure.Storage/tests/unicode_test.cpp diff --git a/BreakingChanges.txt b/BreakingChanges.txt index 032e1f1b..860f3247 100644 --- a/BreakingChanges.txt +++ b/BreakingChanges.txt @@ -1,6 +1,10 @@ Azure Storage Client Library for C++ History of Breaking Changes +Breaking Changes in v1.0: +- Changed return value type of cloud_blob_client::list_blobs_segmented, cloud_blob_container::list_blobs_segmented and cloud_blob_directory::list_blobs_segmented methods from blob_result_segment to list_blob_item_segment +- Removed type blob_result_segment + Breaking Changes in v0.6: - Removed following functions: - cloud_queue_client::list_queues diff --git a/Changelog.txt b/Changelog.txt index c537c7d0..ba14b540 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,6 +1,23 @@ Azure Storage Client Library for C++ History of Changes +Changes in v1.0: +- Changed return value type of cloud_blob_client::list_blobs_segmented, cloud_blob_container::list_blobs_segmented and cloud_blob_directory::list_blobs_segmented methods from blob_result_segment to list_blob_item_segment +- Removed type blob_result_segment +- Redefined following types using result_segment template: + - queue_result_segment + - table_result_segment + - table_query_segment +- Added following functions which retrieve results from service lazily: + - cloud_blob_client::list_containers + - cloud_blob_client::list_blobs + - cloud_blob_container::list_blobs + - cloud_blob_directory::list_blobs + - cloud_queue_client::list_queues + - cloud_table_client::list_tables + - cloud_table::execute_query +- Updated unit test project and unit test guidance to refer to UnitTest++ in GitHub. + Changes in v0.6: - Fixed the bug that cloud_blob::download_range_to_stream corrupted downloaded data if retry succeeded after a failed request - Fixed the bug that cloud_blob::download_range_to_stream might access the target stream after the call completed and led to access violation under a race condition diff --git a/Microsoft.WindowsAzure.Storage.autopkg b/Microsoft.WindowsAzure.Storage.autopkg index ee458056..9bcaefbe 100644 --- a/Microsoft.WindowsAzure.Storage.autopkg +++ b/Microsoft.WindowsAzure.Storage.autopkg @@ -1,7 +1,7 @@ nuget { nuspec { id = wastorage; - version: 0.6.0-preview; + version: 1.0.0; title: Microsoft Azure Storage Client Library for C++; authors: {Microsoft Corporation}; owners: {Microsoft Corporation}; @@ -11,7 +11,7 @@ nuget { summary: "A client library for working with Microsoft Azure storage services including blobs, tables, and queues."; description: @"This client library enables working with the Microsoft Azure storage services which include the blob service for storing binary and text data, the table service for storing structured non-relational data, and the queue service for storing messages that may be accessed by a client. Microsoft Azure Storage team's blog - http://blogs.msdn.com/b/windowsazurestorage/"; - releaseNotes: "Preview release"; + releaseNotes: "Public release"; tags: { Microsoft, Azure, Storage, Table, Blob, Queue, Scalable, windowsazureofficial }; } diff --git a/Microsoft.WindowsAzure.Storage.sln b/Microsoft.WindowsAzure.Storage.sln index c0f2878f..d21cd1a3 100644 --- a/Microsoft.WindowsAzure.Storage.sln +++ b/Microsoft.WindowsAzure.Storage.sln @@ -3,10 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.WindowsAzure.Storage", "Microsoft.WindowsAzure.Storage\Microsoft.WindowsAzure.Storage.vcxproj", "{DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest++.vsnet2005", "Microsoft.WindowsAzure.Storage\tests\UnitTest++\UnitTest++.vsnet2005.vcxproj", "{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.WindowsAzure.Storage.UnitTests", "Microsoft.WindowsAzure.Storage\tests\Microsoft.WindowsAzure.Storage.UnitTests.vcxproj", "{D02FBA48-23CD-4CDF-9BD0-A03295744FA2}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -23,18 +19,6 @@ Global {DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}.Release|Win32.Build.0 = Release|Win32 {DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}.Release|x64.ActiveCfg = Release|x64 {DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}.Release|x64.Build.0 = Release|x64 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|Win32.ActiveCfg = Debug|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|Win32.Build.0 = Debug|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|x64.ActiveCfg = Debug|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|Win32.ActiveCfg = Release|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|Win32.Build.0 = Release|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|x64.ActiveCfg = Release|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Debug|Win32.ActiveCfg = Debug|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Debug|Win32.Build.0 = Debug|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Debug|x64.ActiveCfg = Debug|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Release|Win32.ActiveCfg = Release|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Release|Win32.Build.0 = Release|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Microsoft.WindowsAzure.Storage.v120.sln b/Microsoft.WindowsAzure.Storage.v120.sln index 4467dcd0..9aad08f0 100644 --- a/Microsoft.WindowsAzure.Storage.v120.sln +++ b/Microsoft.WindowsAzure.Storage.v120.sln @@ -1,14 +1,10 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30110.0 +VisualStudioVersion = 12.0.30501.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.WindowsAzure.Storage.v120", "Microsoft.WindowsAzure.Storage\Microsoft.WindowsAzure.Storage.v120.vcxproj", "{DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTest++.vsnet2005.v120", "Microsoft.WindowsAzure.Storage\tests\UnitTest++\UnitTest++.vsnet2005.v120.vcxproj", "{64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.WindowsAzure.Storage.UnitTests.v120", "Microsoft.WindowsAzure.Storage\tests\Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj", "{D02FBA48-23CD-4CDF-9BD0-A03295744FA2}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{995340A4-EECE-4AF0-B29F-AD925585C7FC}" ProjectSection(SolutionItems) = preProject .nuget\NuGet.Config = .nuget\NuGet.Config @@ -32,18 +28,6 @@ Global {DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}.Release|Win32.Build.0 = Release|Win32 {DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}.Release|x64.ActiveCfg = Release|x64 {DCFF75B0-B142-4EC8-992F-3E48F2E3EECE}.Release|x64.Build.0 = Release|x64 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|Win32.ActiveCfg = Debug|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|Win32.Build.0 = Debug|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Debug|x64.ActiveCfg = Debug|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|Win32.ActiveCfg = Release|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|Win32.Build.0 = Release|Win32 - {64A4FEFE-0461-4E95-8CC1-91EF5F57DBC6}.Release|x64.ActiveCfg = Release|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Debug|Win32.ActiveCfg = Debug|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Debug|Win32.Build.0 = Debug|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Debug|x64.ActiveCfg = Debug|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Release|Win32.ActiveCfg = Release|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Release|Win32.Build.0 = Release|Win32 - {D02FBA48-23CD-4CDF-9BD0-A03295744FA2}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Microsoft.WindowsAzure.Storage/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/CMakeLists.txt index 29b3db01..a1c6b914 100644 --- a/Microsoft.WindowsAzure.Storage/CMakeLists.txt +++ b/Microsoft.WindowsAzure.Storage/CMakeLists.txt @@ -61,8 +61,8 @@ set(AZURESTORAGE_LIBRARY azurestorage) set(AZURESTORAGE_LIBRARIES ${AZURESTORAGE_LIBRARY} ${CASABLANCA_LIBRARIES} ${Boost_LIBRARIES} ${Boost_FRAMEWORK} ${OPENSSL_LIBRARIES} ${LibXML++_LIBRARIES} ${UUID_LIBRARIES} ${Glibmm_LIBRARIES}) # Set version numbers centralized -set (AZURESTORAGE_VERSION_MAJOR 0) -set (AZURESTORAGE_VERSION_MINOR 6) +set (AZURESTORAGE_VERSION_MAJOR 1) +set (AZURESTORAGE_VERSION_MINOR 0) set (AZURESTORAGE_VERSION_REVISION 0) # Add sources per configuration diff --git a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj index 4c4964f3..68de533b 100644 --- a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj @@ -69,7 +69,7 @@ - 9386ecc6 + 8705e8e8 true diff --git a/Microsoft.WindowsAzure.Storage/includes/was/blob.h b/Microsoft.WindowsAzure.Storage/includes/was/blob.h index 24874422..82816486 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/blob.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/blob.h @@ -317,9 +317,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. copy_state(copy_state&& other) { *this = std::move(other); @@ -328,7 +328,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. copy_state& operator=(copy_state&& other) { @@ -470,19 +470,19 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. access_condition(access_condition&& other) { *this = std::move(other); } /// - /// Returns a reference to a object. + /// Returns a reference to an object. /// - /// A reference to a set of to use to set properties. - /// A object with properties set. + /// An existing object to use to set properties. + /// An object with properties set. access_condition& operator=(access_condition&& other) { if (this != &other) @@ -879,9 +879,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. lease_break_period(lease_break_period&& other) { *this = std::move(other); @@ -890,7 +890,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. lease_break_period& operator=(lease_break_period&& other) { @@ -980,9 +980,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. lease_time(lease_time&& other) { *this = std::move(other); @@ -991,7 +991,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. lease_time& operator=(lease_time&& other) { @@ -1036,9 +1036,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. blob_container_permissions(blob_container_permissions&& other) { *this = std::move(other); @@ -1047,7 +1047,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. blob_container_permissions& operator=(blob_container_permissions&& other) { @@ -1083,98 +1083,13 @@ namespace azure { namespace storage { blob_container_public_access_type m_public_access; }; - /// - /// Represents a segment of and - /// results, and includes continuation information. - /// - class blob_result_segment - { - public: - blob_result_segment() - { - } - - /// - /// Initializes a new instance of the class. - /// - /// An enumerable collection of blob results. - /// An enumerable collection of blob directories results. - /// The continuation token. - blob_result_segment(std::vector blobs, std::vector directories, azure::storage::continuation_token token) - : m_blobs(std::move(blobs)), m_directories(std::move(directories)), m_continuation_token(std::move(token)) - { - } - -#if defined(_MSC_VER) && _MSC_VER < 1900 - // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, - // have implicitly-declared move constructor and move assignment operator. - - /// - /// Initializes a new instance of the class. - /// - /// A reference to a set of on which to base the new instance. - blob_result_segment(blob_result_segment&& other) - { - *this = std::move(other); - } - - /// - /// Returns a reference to a object. - /// - /// A reference to a set of to use to set properties. - /// A object with properties set. - blob_result_segment& operator=(blob_result_segment&& other) - { - if (this != &other) - { - m_blobs = std::move(other.m_blobs); - m_directories = std::move(other.m_directories); - m_continuation_token = std::move(other.m_continuation_token); - } - return *this; - } -#endif - - /// - /// Gets an enumerable collection of results. - /// - /// A reference to an enumerable collection of results. - const std::vector& blobs() const - { - return m_blobs; - } + class list_blob_item; - /// - /// Gets an enumerable collection of results. - /// - /// A reference to an enumerable collection of results. - const std::vector& directories() const - { - return m_directories; - } + typedef result_segment list_blob_item_segment; + typedef result_iterator list_blob_item_iterator; - /// - /// Gets the continuation token to use to retrieve the next segment of and - /// results. - /// - /// A reference to the . - const azure::storage::continuation_token& continuation_token() const - { - return m_continuation_token; - } - - private: - - std::vector m_blobs; - std::vector m_directories; - azure::storage::continuation_token m_continuation_token; - }; - - /// - /// Represents a segment of results, and - /// includes continuation and pagination information. - /// typedef result_segment container_result_segment; + typedef result_iterator container_result_iterator; /// /// Represents the system properties for a blob. @@ -1197,9 +1112,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob_properties(cloud_blob_properties&& other) { *this = std::move(other); @@ -1208,7 +1123,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob_properties& operator=(cloud_blob_properties&& other) { @@ -1466,9 +1381,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob_shared_access_headers(cloud_blob_shared_access_headers&& other) { *this = std::move(other); @@ -1477,7 +1392,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob_shared_access_headers& operator=(cloud_blob_shared_access_headers&& other) { @@ -1618,9 +1533,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. blob_request_options(blob_request_options&& other) { *this = std::move(other); @@ -1629,7 +1544,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. blob_request_options& operator=(blob_request_options&& other) { @@ -1875,9 +1790,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. block_list_item(block_list_item&& other) { *this = std::move(other); @@ -1886,7 +1801,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. block_list_item& operator=(block_list_item&& other) { @@ -1969,9 +1884,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. page_range(page_range&& other) { *this = std::move(other); @@ -1980,7 +1895,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. page_range& operator=(page_range&& other) { @@ -2133,9 +2048,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob_container_properties(cloud_blob_container_properties&& other) { *this = std::move(other); @@ -2144,7 +2059,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob_container_properties& operator=(cloud_blob_container_properties&& other) { @@ -2275,9 +2190,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob_client(cloud_blob_client&& other) { *this = std::move(other); @@ -2286,7 +2201,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob_client& operator=(cloud_blob_client&& other) { @@ -2306,6 +2221,37 @@ namespace azure { namespace storage { /// The authentication scheme. WASTORAGE_API void set_authentication_scheme(azure::storage::authentication_scheme value) override; + /// + /// Returns a that can be used to to lazily enumerate a collection of containers. + /// + /// A that can be used to to lazily enumerate a collection of containers. + container_result_iterator list_containers() const + { + return list_containers(utility::string_t(), container_listing_details::none, 0, blob_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of containers. + /// + /// The container name prefix. + /// A that can be used to to lazily enumerate a collection of containers. + container_result_iterator list_containers(const utility::string_t& prefix) const + { + return list_containers(prefix, container_listing_details::none, 0, blob_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of containers. + /// + /// The container name prefix. + /// A enumeration describing which items to include in the listing. + /// A non-negative integer value that indicates the maximum number of results to be returned. + /// If this value is zero, the maximum possible number of results will be returned. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. + /// A that can be used to to lazily enumerate a collection of containers. + WASTORAGE_API container_result_iterator list_containers(const utility::string_t& prefix, container_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const; + /// /// Returns a result segment containing a collection of objects. /// @@ -2331,7 +2277,7 @@ namespace azure { namespace storage { /// Returns a result segment containing a collection of objects. /// /// The container name prefix. - /// A value that indicates whether to return container metadata with the listing. + /// A enumeration describing which items to include in the listing. /// A non-negative integer value that indicates the maximum number of results to be returned /// in the result segment, up to the per-operation limit of 5000. If this value is 0, the maximum possible number of results will be returned, up to 5000. /// A returned by a previous listing operation. @@ -2378,21 +2324,41 @@ namespace azure { namespace storage { WASTORAGE_API pplx::task list_containers_segmented_async(const utility::string_t& prefix, container_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; /// - /// Returns a result segment containing a collection of blob items - /// in the container. + /// Returns a that can be used to to lazily enumerate a collection of blob items. + /// + /// The blob name prefix. + /// A that can be used to to lazily enumerate a collection of blob items. + list_blob_item_iterator list_blobs(const utility::string_t& prefix) const + { + return list_blobs(prefix, false, blob_listing_details::none, 0, blob_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of blob items. + /// + /// The blob name prefix. + /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. + /// A enumeration describing which items to include in the listing. + /// A non-negative integer value that indicates the maximum number of results to be returned. + /// If this value is zero, the maximum possible number of results will be returned. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. + /// A that can be used to to lazily enumerate a collection of blob items. + WASTORAGE_API list_blob_item_iterator list_blobs(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const; + + /// + /// Returns a containing a collection of blob items in the container. /// /// The blob name prefix. /// A returned by a previous listing operation. - /// A containing blob items, which may implement - /// or . - blob_result_segment list_blobs_segmented(const utility::string_t& prefix, const continuation_token& token) const + /// A containing a collection of blob items in the container. + list_blob_item_segment list_blobs_segmented(const utility::string_t& prefix, const continuation_token& token) const { return list_blobs_segmented_async(prefix, token).get(); } /// - /// Returns a result segment containing a collection of blob items - /// in the container. + /// Returns a containing a collection of blob items in the container. /// /// The blob name prefix. /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. @@ -2402,25 +2368,25 @@ namespace azure { namespace storage { /// A returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. - /// A containing blob items, which may implement or . - blob_result_segment list_blobs_segmented(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const + /// A containing a collection of blob items in the container. + list_blob_item_segment list_blobs_segmented(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { return list_blobs_segmented_async(prefix, use_flat_blob_listing, includes, max_results, token, options, context).get(); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items in the container. + /// Intitiates an asynchronous operation to return a containing a collection of blob items in the container. /// /// The blob name prefix. /// A returned by a previous listing operation. - /// A object of type that represents the current operation. - pplx::task list_blobs_segmented_async(const utility::string_t& prefix, const continuation_token& token) const + /// A object of type that represents the current operation. + pplx::task list_blobs_segmented_async(const utility::string_t& prefix, const continuation_token& token) const { return list_blobs_segmented_async(prefix, false, blob_listing_details::none, 0, token, blob_request_options(), operation_context()); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items in the container. + /// Intitiates an asynchronous operation to return a containing a collection of blob items in the container. /// /// The blob name prefix. /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. @@ -2430,8 +2396,8 @@ namespace azure { namespace storage { /// A returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. - /// A object of type that represents the current operation. - WASTORAGE_API pplx::task list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; + /// A object of type that represents the current operation. + WASTORAGE_API pplx::task list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; /// /// Gets the service properties for the Blob service client. @@ -2603,6 +2569,8 @@ namespace azure { namespace storage { m_directory_delimiter = protocol::directory_delimiter; } + static void parse_blob_name_prefix(const utility::string_t& prefix, utility::string_t& container_name, utility::string_t& actual_prefix); + blob_request_options m_default_request_options; utility::string_t m_directory_delimiter; }; @@ -2652,9 +2620,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob_container(cloud_blob_container&& other) { *this = std::move(other); @@ -2663,7 +2631,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob_container& operator=(cloud_blob_container&& other) { @@ -3185,12 +3153,34 @@ namespace azure { namespace storage { /// A object that represents the current operation. WASTORAGE_API pplx::task delete_container_if_exists_async(const access_condition& condition, const blob_request_options& options, operation_context context); + /// + /// Returns a that can be used to to lazily enumerate a collection of blob items in the container. + /// + /// A that can be used to to lazily enumerate a collection of blob items in the container. + list_blob_item_iterator list_blobs() const + { + return list_blobs(utility::string_t(), false, blob_listing_details::none, 0, blob_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of blob items in the the container. + /// + /// The blob name prefix. + /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. + /// A enumeration describing which items to include in the listing. + /// A non-negative integer value that indicates the maximum number of results to be returned. + /// If this value is zero, the maximum possible number of results will be returned. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. + /// A that can be used to to lazily enumerate a collection of blob items in the the container. + WASTORAGE_API list_blob_item_iterator list_blobs(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const; + /// /// Returns a result segment containing a collection of blob items in the container. /// /// A continuation token returned by a previous listing operation. - /// A containing blob items, which may implement or . - blob_result_segment list_blobs_segmented(const continuation_token& token) const + /// A containing blob items, which may implement or . + list_blob_item_segment list_blobs_segmented(const continuation_token& token) const { return list_blobs_segmented_async(token).get(); } @@ -3201,7 +3191,7 @@ namespace azure { namespace storage { /// The blob name prefix. /// A continuation token returned by a previous listing operation. /// A result segment containing objects that implement and . - blob_result_segment list_blobs_segmented(const utility::string_t& prefix, const continuation_token& token) const + list_blob_item_segment list_blobs_segmented(const utility::string_t& prefix, const continuation_token& token) const { return list_blobs_segmented_async(prefix, token).get(); } @@ -3217,37 +3207,37 @@ namespace azure { namespace storage { /// A continuation token returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. - /// A containing blob items, which may implement or . - blob_result_segment list_blobs_segmented(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const + /// A containing a collection of blob items in the container. + list_blob_item_segment list_blobs_segmented(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { return list_blobs_segmented_async(prefix, use_flat_blob_listing, includes, max_results, token, options, context).get(); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items + /// Intitiates an asynchronous operation to return a containing a collection of blob items /// in the container. /// /// A continuation token returned by a previous listing operation. - /// A object of type that represents the current operation. - pplx::task list_blobs_segmented_async(const continuation_token& token) const + /// A object of type that represents the current operation. + pplx::task list_blobs_segmented_async(const continuation_token& token) const { return list_blobs_segmented_async(utility::string_t(), token); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items + /// Intitiates an asynchronous operation to return a containing a collection of blob items /// in the container. /// /// The blob name prefix. /// A continuation token returned by a previous listing operation. - /// A object of type that represents the current operation. - pplx::task list_blobs_segmented_async(const utility::string_t& prefix, const continuation_token& token) const + /// A object of type that represents the current operation. + pplx::task list_blobs_segmented_async(const utility::string_t& prefix, const continuation_token& token) const { return list_blobs_segmented_async(prefix, false, blob_listing_details::none, 0, token, blob_request_options(), operation_context()); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items + /// Intitiates an asynchronous operation to return a containing a collection of blob items /// in the container. /// /// The blob name prefix. @@ -3258,8 +3248,8 @@ namespace azure { namespace storage { /// A continuation token returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. - /// A object of type that represents the current operation. - WASTORAGE_API pplx::task list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; + /// A object of type that represents the current operation. + WASTORAGE_API pplx::task list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; /// /// Sets permissions for the container. @@ -3470,21 +3460,14 @@ namespace azure { namespace storage { { } - /// - /// Initializes a new instance of the class. - /// - /// Name of the virtual directory. - /// The container. - cloud_blob_directory(utility::string_t name, cloud_blob_container container); - #if defined(_MSC_VER) && _MSC_VER < 1900 // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob_directory(cloud_blob_directory&& other) { *this = std::move(other); @@ -3493,7 +3476,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob_directory& operator=(cloud_blob_directory&& other) { @@ -3566,20 +3549,40 @@ namespace azure { namespace storage { /// The virtual directory's parent directory. WASTORAGE_API cloud_blob_directory get_parent_reference() const; + /// + /// Returns a that can be used to to lazily enumerate a collection of blob items in the virtual directory. + /// + /// A that can be used to to lazily enumerate a collection of blob items in the virtual directory. + list_blob_item_iterator list_blobs() const + { + return list_blobs(false, blob_listing_details::none, 0, blob_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of blob items in the the virtual directory. + /// + /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. + /// A enumeration describing which items to include in the listing. + /// A non-negative integer value that indicates the maximum number of results to be returned. + /// If this value is zero, the maximum possible number of results will be returned. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. + /// A that can be used to to lazily enumerate a collection of blob items in the the virtual directory. + WASTORAGE_API list_blob_item_iterator list_blobs(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const; + /// /// Returns a result segment containing a collection of blob items /// in the container. /// /// A continuation token returned by a previous listing operation. - /// A containing blob items, which may implement or . - blob_result_segment list_blobs_segmented(const continuation_token& token) const + /// A containing a collection of blob items in the container. + list_blob_item_segment list_blobs_segmented(const continuation_token& token) const { return list_blobs_segmented_async(token).get(); } /// - /// Returns a result segment containing a collection of blob items - /// in the container. + /// Returns a containing a collection of blob items in the container. /// /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. /// A enumeration describing which items to include in the listing. @@ -3588,25 +3591,25 @@ namespace azure { namespace storage { /// A continuation token returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. - /// A containing blob items, which may implement or . - blob_result_segment list_blobs_segmented(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const + /// A containing a collection of blob items in the container. + list_blob_item_segment list_blobs_segmented(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { return list_blobs_segmented_async(use_flat_blob_listing, includes, max_results, token, options, context).get(); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items + /// Intitiates an asynchronous operation to return a containing a collection of blob items /// in the container. /// /// A continuation token returned by a previous listing operation. - /// A object of type that that represents the current operation. - pplx::task list_blobs_segmented_async(const continuation_token& token) const + /// A object of type that that represents the current operation. + pplx::task list_blobs_segmented_async(const continuation_token& token) const { return list_blobs_segmented_async(false, blob_listing_details::none, 0, token, blob_request_options(), operation_context()); } /// - /// Intitiates an asynchronous operation to return a result segment containing a collection of blob items + /// Intitiates an asynchronous operation to return a containing a collection of blob items /// in the container. /// /// Indicates whether to list blobs in a flat listing, or whether to list blobs hierarchically, by virtual directory. @@ -3616,8 +3619,8 @@ namespace azure { namespace storage { /// A continuation token returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. - /// A object of type that represents the current operation. - WASTORAGE_API pplx::task list_blobs_segmented_async(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; + /// A object of type that represents the current operation. + WASTORAGE_API pplx::task list_blobs_segmented_async(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const; /// /// Gets the Blob service client for the virtual directory. @@ -3666,9 +3669,20 @@ namespace azure { namespace storage { private: + /// + /// Initializes a new instance of the class. + /// + /// Name of the virtual directory. + /// The container. + WASTORAGE_API cloud_blob_directory(utility::string_t name, cloud_blob_container container); + utility::string_t m_name; cloud_blob_container m_container; storage_uri m_uri; + + friend class cloud_blob_container; + friend class cloud_blob; + friend class list_blob_item; }; /// @@ -3711,9 +3725,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_blob(cloud_blob&& other) { *this = std::move(other); @@ -3722,7 +3736,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_blob& operator=(cloud_blob&& other) { @@ -4729,7 +4743,7 @@ namespace azure { namespace storage { /// The name of the blob. /// The snapshot timestamp, if the blob is a snapshot. /// A reference to the parent container. - cloud_blob(utility::string_t name, utility::string_t snapshot_time, cloud_blob_container container); + WASTORAGE_API cloud_blob(utility::string_t name, utility::string_t snapshot_time, cloud_blob_container container); /// /// Initializes a new instance of the class. @@ -4740,7 +4754,7 @@ namespace azure { namespace storage { /// A set of properties for the blob. /// User-defined metadata for the blob. /// the state of the most recent or pending copy operation. - cloud_blob(utility::string_t name, utility::string_t snapshot_time, cloud_blob_container container, cloud_blob_properties properties, cloud_metadata metadata, azure::storage::copy_state copy_state); + WASTORAGE_API cloud_blob(utility::string_t name, utility::string_t snapshot_time, cloud_blob_container container, cloud_blob_properties properties, cloud_metadata metadata, azure::storage::copy_state copy_state); void assert_no_snapshot() const; @@ -4765,6 +4779,7 @@ namespace azure { namespace storage { friend class cloud_blob_container; friend class cloud_blob_directory; + friend class list_blob_item; }; /// @@ -4830,9 +4845,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_block_blob(cloud_block_blob&& other) { *this = std::move(other); @@ -4841,7 +4856,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_block_blob& operator=(cloud_block_blob&& other) { @@ -5248,7 +5263,7 @@ namespace azure { namespace storage { /// /// The name of the blob. /// The snapshot timestamp, if the blob is a snapshot. - /// A reference to the parent container. + /// A object. cloud_block_blob(utility::string_t name, utility::string_t snapshot_time, cloud_blob_container container) : cloud_blob(std::move(name), std::move(snapshot_time), std::move(container)) { @@ -5322,9 +5337,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_page_blob(cloud_page_blob&& other) { *this = std::move(other); @@ -5333,7 +5348,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_page_blob& operator=(cloud_page_blob&& other) { @@ -5895,4 +5910,120 @@ namespace azure { namespace storage { friend class cloud_blob_directory; }; + /// + /// Represents an item that may be returned by a blob listing operation. + /// + class list_blob_item + { + public: + + /// + /// Initializes a new instance of the class that represents a cloud blob. + /// + /// A object. + /// The name of the blob. + /// The snapshot timestamp, if the blob is a snapshot. + /// A reference to the parent container. + /// A set of properties for the blob. + /// User-defined metadata for the blob. + /// the state of the most recent or pending copy operation. + explicit list_blob_item(utility::string_t blob_name, utility::string_t snapshot_time, cloud_blob_container container, cloud_blob_properties properties, cloud_metadata metadata, copy_state copy_state) + : m_is_blob(true), m_name(std::move(blob_name)), m_snapshot_time(std::move(snapshot_time)), m_container(std::move(container)), + m_properties(std::move(properties)), m_metadata(std::move(metadata)), m_copy_state(std::move(copy_state)) + { + } + + /// + /// Initializes a new instance of the class that represents a cloud blob directory. + /// + /// Name of the virtual directory. + /// The container. + explicit list_blob_item(utility::string_t directory_name, cloud_blob_container container) + : m_is_blob(false), m_name(std::move(directory_name)), m_container(std::move(container)) + { + } + +#if defined(_MSC_VER) && _MSC_VER < 1900 + // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, + // have implicitly-declared move constructor and move assignment operator. + + /// + /// Initializes a new instance of the class based on an existing instance. + /// + /// An existing object. + list_blob_item(list_blob_item&& other) + { + *this = std::move(other); + } + + /// + /// Returns a reference to a object. + /// + /// An existing object to use to set properties. + /// A object with properties set. + list_blob_item& operator=(list_blob_item&& other) + { + if (this != &other) + { + m_is_blob = other.m_is_blob; + m_name = std::move(other.m_name); + m_container = std::move(other.m_container); + m_snapshot_time = std::move(other.m_snapshot_time); + m_properties = std::move(other.m_properties); + m_metadata = std::move(other.m_metadata); + m_copy_state = std::move(other.m_copy_state); + } + + return *this; + } +#endif + + /// + /// Gets a value indicating whether this represents a cloud blob or a cloud blob directory. + /// + /// true if this represents a cloud blob; otherwise, false. + bool is_blob() const + { + return m_is_blob; + } + + /// + /// Returns the item as a object, if and only if it represents a cloud blob. + /// + /// A object. + cloud_blob as_blob() const + { + if (!is_blob()) + { + throw std::runtime_error("Cannot access a cloud blob directory as cloud blob "); + } + + return cloud_blob(m_name, m_snapshot_time, m_container, m_properties, m_metadata, m_copy_state); + } + + /// + /// Returns the item as a object, if and only if it represents a cloud blob directory. + /// + /// A object. + cloud_blob_directory as_directory() const + { + if (is_blob()) + { + throw std::runtime_error("Cannot access a cloud blob as cloud blob directory"); + } + + return cloud_blob_directory(m_name, m_container); + } + + private: + + bool m_is_blob; + utility::string_t m_name; + cloud_blob_container m_container; + utility::string_t m_snapshot_time; + cloud_blob_properties m_properties; + cloud_metadata m_metadata; + copy_state m_copy_state; + }; + }} // namespace azure::storage diff --git a/Microsoft.WindowsAzure.Storage/includes/was/common.h b/Microsoft.WindowsAzure.Storage/includes/was/common.h index 501a591f..d18e6726 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/common.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/common.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include "core.h" @@ -71,9 +72,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. continuation_token(continuation_token&& other) { *this = std::move(other); @@ -82,7 +83,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. continuation_token& operator=(continuation_token&& other) { @@ -177,9 +178,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. result_segment(result_segment&& other) { *this = std::move(other); @@ -188,7 +189,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. result_segment& operator=(result_segment&& other) { @@ -225,6 +226,196 @@ namespace azure { namespace storage { azure::storage::continuation_token m_continuation_token; }; + /// + /// Represents a result iterator that could be used to enumerate results in the result set in a lazy way. + /// + /// The type of the result. + template + class result_iterator : public std::iterator + { + public: + + /// + /// Initializes a new instance of the class. + /// + result_iterator() : + m_result_generator(nullptr), + m_segment_index(0), + m_returned_results(0), + m_max_results(0), + m_max_results_per_segment(0) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The result segment generator. + /// A non-negative integer value that indicates the maximum number of results to be returned + /// by the result iterator. If this value is 0, the maximum possible number of results will be returned. + /// A non-negative integer value that indicates the maximum number of results to + /// be returned in one segment. If this value is 0, the maximum possible number of results returned in a segment will be + // determined by individual service. + result_iterator(std::function(const continuation_token &, size_t)> result_generator, utility::size64_t max_results, size_t max_results_per_segment) : + m_result_generator(std::move(result_generator)), + m_segment_index(0), + m_returned_results(0), + m_max_results(max_results), + m_max_results_per_segment(max_results_per_segment) + { + fetch_first_segment(); + } + +#if defined(_MSC_VER) && _MSC_VER < 1900 + // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, + // have implicitly-declared move constructor and move assignment operator. + + /// + /// Initializes a new instance of the class. + /// + /// A reference to a set of on which to base the new instance. + result_iterator(result_iterator&& other) + { + *this = std::move(other); + } + + /// + /// Returns a reference to a object. + /// + /// A reference to a set of to use to set properties. + /// A object with properties set. + result_iterator& operator=(result_iterator&& other) + { + if (this != &other) + { + m_result_generator = std::move(other.m_result_generator); + m_result_segment = std::move(other.m_result_segment); + m_segment_index = other.m_segment_index; + m_returned_results = other.m_returned_results; + m_max_results = other.m_max_results; + m_max_results_per_segment = other.m_max_results_per_segment; + } + + return *this; + } +#endif + + const result_type& operator*() const + { + if (passed_the_end()) + { + throw std::runtime_error("cannot dereference past-the-end iterator"); + } + + return m_result_segment.results()[m_segment_index]; + } + + const result_type* operator->() const + { + return (std::pointer_traits::pointer_to(**this)); + } + + result_iterator& operator++() + { + // preincrement + // - if the iterator has passed the end, do nothing + // - if any exception is thrown within the method, do nothing + if (!passed_the_end()) + { + if (m_segment_index + 1 == m_result_segment.results().size() && !m_result_segment.continuation_token().empty()) + { + fetch_next_segment(); + } + else + { + m_segment_index++; + } + + m_returned_results++; + } + + return (*this); + } + + result_iterator operator++(int) + { + // postincrement + result_iterator tmp = *this; + ++*this; + return (tmp); + } + + bool operator==(const result_iterator& rhs) const + { + // test for iterator equality + // - comparison of two past-the-end iterators returns true + // - comparison of a non-end iterator and a past-the-end iterators returns false + // - comparison of two non-end iterators returns false + return passed_the_end() && rhs.passed_the_end(); + } + + bool operator!=(const result_iterator& rhs) const + { + return (!(*this == rhs)); + } + + private: + + void fetch_first_segment() + { + if (nullptr != m_result_generator) + { + m_result_segment = m_result_generator(continuation_token(), get_remaining_results_num()); + m_segment_index = 0; + + if (m_result_segment.results().empty()) + { + // continue if returned result segment is empty + fetch_next_segment(); + } + } + } + + void fetch_next_segment() + { + if (nullptr != m_result_generator && !m_result_segment.continuation_token().empty()) + { + auto tmp_segment = m_result_generator(m_result_segment.continuation_token(), get_remaining_results_num()); + while (tmp_segment.results().empty() && !tmp_segment.continuation_token().empty()) + { + tmp_segment = m_result_generator(tmp_segment.continuation_token(), get_remaining_results_num()); + } + + m_result_segment = std::move(tmp_segment); + m_segment_index = 0; + } + } + + size_t get_remaining_results_num() const + { + if (m_max_results == 0) + { + // 0 indicates to return maximum possible number of results + return m_max_results_per_segment; + } + + return (size_t)std::min(m_max_results - m_returned_results, (utility::size64_t)m_max_results_per_segment); + } + + bool passed_the_end() const + { + return (m_segment_index == m_result_segment.results().size() && m_result_segment.continuation_token().empty()) || + (m_max_results > 0 && m_returned_results >= m_max_results); + } + + std::function(const continuation_token &, size_t)> m_result_generator; + result_segment m_result_segment; + size_t m_segment_index; + utility::size64_t m_returned_results; + utility::size64_t m_max_results; + size_t m_max_results_per_segment; + }; + /// /// Specifies which items to include when setting service properties. /// @@ -244,9 +435,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. service_properties_includes(service_properties_includes&& other) { *this = std::move(other); @@ -255,7 +446,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. service_properties_includes& operator=(service_properties_includes&& other) { @@ -391,9 +582,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. logging_properties(logging_properties&& other) { *this = std::move(other); @@ -402,7 +593,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. logging_properties& operator=(logging_properties&& other) { @@ -557,9 +748,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. metrics_properties(metrics_properties&& other) { *this = std::move(other); @@ -568,7 +759,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. metrics_properties& operator=(metrics_properties&& other) { @@ -702,9 +893,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cors_rule(cors_rule&& other) { *this = std::move(other); @@ -713,7 +904,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cors_rule& operator=(cors_rule&& other) { @@ -876,9 +1067,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. service_properties(service_properties&& other) { *this = std::move(other); @@ -887,7 +1078,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. service_properties& operator=(service_properties&& other) { @@ -1086,9 +1277,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. geo_replication_stats(geo_replication_stats&& other) { *this = std::move(other); @@ -1097,7 +1288,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. geo_replication_stats& operator=(geo_replication_stats&& other) { @@ -1167,9 +1358,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. service_stats(service_stats&& other) { *this = std::move(other); @@ -1178,7 +1369,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. service_stats& operator=(service_stats&& other) { @@ -1403,27 +1594,27 @@ namespace azure { namespace storage { #ifndef WIN32 /// - /// Gets the logger object on this op_context. + /// Gets the logger object on this operation context. /// - /// The logger object used by this op_context. + /// The object used by this operation context. boost::log::sources::severity_logger& logger() { return m_logger; } /// - /// Gets the logger object on this op_context. + /// Gets the logger object on this operation context. /// - /// The logger object used by this op_context. + /// The object used by this operation context. const boost::log::sources::severity_logger& logger() const { return m_logger; } /// - /// Sets the logger object on this op_context. + /// Sets the logger object on this operation context. /// - /// The logger object to use for requests made by this op_context. + /// The object to use for requests made by this operation context. void set_logger(boost::log::sources::severity_logger logger) { m_logger = std::move(logger); @@ -1611,27 +1802,27 @@ namespace azure { namespace storage { #ifndef WIN32 /// - /// Gets the logger object on this op_context. + /// Gets the logger object on this operation context. /// - /// The logger object used by this op_context. + /// The object used by this operation context. boost::log::sources::severity_logger& logger() { return m_impl->logger(); } /// - /// Gets the logger object on this op_context. + /// Gets the logger object on this operation context. /// - /// The logger object used by this op_context. + /// The object used by this operation context. const boost::log::sources::severity_logger& logger() const { return m_impl->logger(); } /// - /// Sets the logger object on this op_context. + /// Sets the logger object on this operation context. /// - /// The logger object to use for requests made by this op_context. + /// The object to use for requests made by this operation context. void set_logger(boost::log::sources::severity_logger logger) { m_impl->set_logger(std::move(logger)); @@ -1883,9 +2074,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_permissions(cloud_permissions&& other) { *this = std::move(other); @@ -1894,7 +2085,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_permissions& operator=(cloud_permissions&& other) { @@ -1953,9 +2144,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. request_options(request_options&& other) { *this = std::move(other); @@ -1964,7 +2155,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. request_options& operator=(request_options&& other) { diff --git a/Microsoft.WindowsAzure.Storage/includes/was/core.h b/Microsoft.WindowsAzure.Storage/includes/was/core.h index d585e281..d43eea51 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/core.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/core.h @@ -119,9 +119,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. storage_uri(storage_uri&& other) { *this = std::move(other); @@ -130,7 +130,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. storage_uri& operator=(storage_uri&& other) { @@ -259,9 +259,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. storage_credentials(storage_credentials&& other) { *this = std::move(other); @@ -270,7 +270,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. storage_credentials& operator=(storage_credentials&& other) { @@ -393,9 +393,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. option_with_default(option_with_default&& other) { *this = std::move(other); @@ -404,7 +404,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. option_with_default& operator=(option_with_default&& other) { @@ -497,9 +497,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. storage_extended_error(storage_extended_error&& other) { *this = std::move(other); @@ -508,7 +508,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. storage_extended_error& operator=(storage_extended_error&& other) { @@ -613,9 +613,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. request_result(request_result&& other) { *this = std::move(other); @@ -624,7 +624,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. request_result& operator=(request_result&& other) { @@ -728,9 +728,9 @@ namespace azure { namespace storage { } /// - /// Gets the content MD5 hash for the request. + /// Gets the content-MD5 hash for the request. /// - /// The content MD5 hash for the request. + /// A string containing the content-MD5 hash for the request. const utility::string_t& content_md5() const { return m_content_md5; @@ -801,7 +801,7 @@ namespace azure { namespace storage { /// Initializes a new instance of the class. /// /// The error message. - /// The inner exception. + /// A object containing the inner exception. /// Indicates whether the request is retryable. storage_exception(const std::string& message, std::exception_ptr inner_exception, bool retryable = true) : std::runtime_error(message), m_retryable(retryable), m_inner_exception(inner_exception) @@ -824,7 +824,7 @@ namespace azure { namespace storage { /// /// The error message. /// The request result. - /// The inner exception. + /// A object containing the inner exception. /// Indicates whether the request is retryable. storage_exception(const std::string& message, request_result result, std::exception_ptr inner_exception, bool retryable = true) : std::runtime_error(message), m_result(std::move(result)), m_retryable(retryable), m_inner_exception(inner_exception) @@ -853,7 +853,7 @@ namespace azure { namespace storage { /// Gets the inner exception object that is the cause for the current . /// /// - /// An exception_ptr object. It points to the inner exception that is the cause for the current + /// A object that points to the inner exception associated with the current /// . A null exception_ptr is returned if there is no inner exception /// object. /// @@ -893,9 +893,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. retry_context(retry_context&& other) { *this = std::move(other); @@ -904,7 +904,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. retry_context& operator=(retry_context&& other) { @@ -940,7 +940,7 @@ namespace azure { namespace storage { /// /// Gets the target location for the next retry. /// - /// The target location for the next retry. + /// The for the next retry. storage_location next_location() const { return m_next_location; @@ -949,7 +949,7 @@ namespace azure { namespace storage { /// /// Gets the location mode for subsequent retries. /// - /// The location mode for subsequent retries. + /// The for subsequent retries. location_mode current_location_mode() const { return m_current_location_mode; @@ -994,9 +994,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. retry_info(retry_info&& other) { *this = std::move(other); @@ -1005,7 +1005,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. retry_info& operator=(retry_info&& other) { diff --git a/Microsoft.WindowsAzure.Storage/includes/was/error_code_strings.h b/Microsoft.WindowsAzure.Storage/includes/was/error_code_strings.h index df5562eb..91e1b07f 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/error_code_strings.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/error_code_strings.h @@ -196,7 +196,7 @@ namespace azure { namespace storage { namespace protocol { const utility::string_t error_code_condition_headers_not_supported(U("ConditionHeadersNotSupported")); /// - /// Multiple condition headers are not supported. + /// Multiple conditional headers are not supported. /// const utility::string_t error_code_multiple_condition_headers_not_supported(U("MultipleConditionHeadersNotSupported")); @@ -238,17 +238,17 @@ namespace azure { namespace storage { namespace protocol { // This section provides error code strings that are specific to the Blob service. /// - /// Error code that may be returned when the specified block or blob is invalid. + /// The specified block or blob is invalid. /// const utility::string_t error_code_invalid_blob_or_block(U("InvalidBlobOrBlock")); /// - /// Error code that may be returned when a block ID is invalid. + /// The block ID is invalid. /// const utility::string_t error_code_invalid_block_id(U("InvalidBlockId")); /// - /// Error code that may be returned when a block list is invalid. + /// The block list is invalid. /// const utility::string_t error_code_invalid_block_list(U("InvalidBlockList")); @@ -258,7 +258,7 @@ namespace azure { namespace storage { namespace protocol { const utility::string_t error_code_container_not_found(U("ContainerNotFound")); /// - /// Error code that may be returned when a blob with the specified address cannot be found. + /// The blob with the specified address cannot be found. /// const utility::string_t error_code_blob_not_found(U("BlobNotFound")); @@ -278,142 +278,142 @@ namespace azure { namespace storage { namespace protocol { const utility::string_t error_code_container_being_deleted(U("ContainerBeingDeleted")); /// - /// Error code that may be returned when a client attempts to create a blob that already exists. + /// The specified blob already exists. /// const utility::string_t error_code_blob_already_exists(U("BlobAlreadyExists")); /// - /// Error code that may be returned when there is currently no lease on the blob. + /// There is currently no lease on the blob. /// const utility::string_t error_code_lease_not_present_with_blob_operation(U("LeaseNotPresentWithBlobOperation")); /// - /// Error code that may be returned when there is currently no lease on the container. + /// There is currently no lease on the container. /// const utility::string_t error_code_lease_not_present_with_container_operation(U("LeaseNotPresentWithContainerOperation")); /// - /// Error code that may be returned when a lease ID was specified, but the lease has expired. + /// The specified lease has expired. /// const utility::string_t error_code_lease_lost(U("LeaseLost")); /// - /// Error code that may be returned when the lease ID specified did not match the lease ID for the blob. + /// The specified lease ID does not match the lease ID for the blob. /// const utility::string_t error_code_lease_id_mismatch_with_blob_operation(U("LeaseIdMismatchWithBlobOperation")); /// - /// Error code that may be returned when the lease ID specified did not match the lease ID for the container. + /// The specified lease ID does not match the lease ID for the container. /// const utility::string_t error_code_lease_id_mismatch_with_container_operation(U("LeaseIdMismatchWithContainerOperation")); /// - /// Error code that may be returned when there is currently a lease on the resource and no lease ID was specified in the request. + /// There is currently a lease on the resource and no lease ID was specified in the request. /// const utility::string_t error_code_lease_id_missing(U("LeaseIdMissing")); /// - /// Error code that may be returned when there is currently no lease on the resource. + /// There is currently no lease on the resource. /// const utility::string_t error_code_lease_not_present_with_lease_operation(U("LeaseNotPresentWithLeaseOperation")); /// - /// Error code that may be returned when the lease ID specified did not match the lease ID. + /// The specified lease ID specified does not match the lease operation. /// const utility::string_t error_code_lease_id_mismatch_with_lease_operation(U("LeaseIdMismatchWithLeaseOperation")); /// - /// Error code that may be returned when there is already a lease present. + /// There is already a lease present. /// const utility::string_t error_code_lease_already_present(U("LeaseAlreadyPresent")); /// - /// Error code that may be returned when the lease has already been broken and cannot be broken again. + /// The lease has already been broken and cannot be broken again. /// const utility::string_t error_code_lease_already_broken(U("LeaseAlreadyBroken")); /// - /// Error code that may be returned when the lease ID matched, but the lease has been broken explicitly and cannot be renewed. + /// The lease has been broken explicitly and cannot be renewed. /// const utility::string_t error_code_lease_is_broken_and_cannot_be_renewed(U("LeaseIsBrokenAndCannotBeRenewed")); /// - /// Error code that may be returned when the lease ID matched, but the lease is breaking and cannot be acquired. + /// The lease is breaking and cannot be acquired. /// const utility::string_t error_code_lease_is_breaking_and_cannot_be_acquired(U("LeaseIsBreakingAndCannotBeAcquired")); /// - /// Error code that may be returned when the lease ID matched, but the lease is breaking and cannot be changed. + /// The lease is breaking and cannot be changed. /// const utility::string_t error_code_lease_is_breaking_and_cannot_be_changed(U("LeaseIsBreakingAndCannotBeChanged")); /// - /// Error code that may be returned when the destination of a copy operation has a lease of fixed duration. + /// The destination of a copy operation has a lease of fixed duration. /// const utility::string_t error_code_infinite_lease_duration_required(U("InfiniteLeaseDurationRequired")); /// - /// Error code that may be returned when the operation is not permitted because the blob has snapshots. + /// The operation is not permitted because the blob has snapshots. /// const utility::string_t error_code_snapshots_present(U("SnapshotsPresent")); /// - /// Error code that may be returned when the blob type is invalid for this operation. + /// The blob type is invalid for this operation. /// const utility::string_t error_code_invalid_blob_type(U("InvalidBlobType")); /// - /// Error code that may be returned when the operation on page blobs uses a version prior to 2009-09-19. + /// The operation on page blobs uses a version prior to 2009-09-19. /// const utility::string_t error_code_invalid_version_for_page_blob_operation(U("InvalidVersionForPageBlobOperation")); /// - /// Error code that may be returned when the page range specified is invalid. + /// The page range specified is invalid. /// const utility::string_t error_code_invalid_page_range(U("InvalidPageRange")); /// - /// Error code that may be returned when the sequence number condition specified was not met. + /// The sequence number condition specified was not met. /// const utility::string_t error_code_sequence_number_condition_not_met(U("SequenceNumberConditionNotMet")); /// - /// Error code that may be returned when the sequence number increment cannot be performed because it would result in overflow of the sequence number. + /// The sequence number increment cannot be performed because it would result in overflow of the sequence number. /// const utility::string_t error_code_sequence_number_increment_too_large(U("SequenceNumberIncrementTooLarge")); /// - /// Error code that may be returned when the source condition specified using HTTP conditional header(s) is not met. + /// The source condition specified using HTTP conditional header(s) is not met. /// const utility::string_t error_code_source_condition_not_met(U("SourceConditionNotMet")); /// - /// Error code that may be returned when the target condition specified using HTTP conditional header(s) is not met. + /// The target condition specified using HTTP conditional header(s) is not met. /// const utility::string_t error_code_target_condition_not_met(U("TargetConditionNotMet")); /// - /// Error code that may be returned when the copy source account and destination account are not the same. + /// The source and destination accounts for the copy operation are not the same. /// const utility::string_t error_code_copy_across_accounts_not_supported(U("CopyAcrossAccountsNotSupported")); /// - /// Error code that may be returned when the source of a copy cannot be accessed. + /// The source for the copy operation cannot be accessed. /// const utility::string_t error_code_cannot_verify_copy_source(U("CannotVerifyCopySource")); /// - /// Error code that may be returned when an attempt to modify the destination of a pending copy is made. + /// An attempt to modify the destination of a pending copy operation is made. /// const utility::string_t error_code_pending_copy_operation(U("PendingCopyOperation")); /// - /// Error code that may be returned when an Abort Copy operation is called when there is no pending copy. + /// An Abort Copy operation is called when there is no pending copy operation. /// const utility::string_t error_code_no_pending_copy_operation(U("NoPendingCopyOperation")); /// - /// Error code that may be returned when the copy ID specified in an Abort Copy operation does not match the current pending copy ID. + /// The copy ID specified in an Abort Copy operation does not match the current pending copy operation ID. /// const utility::string_t error_code_copy_id_mismatch(U("CopyIdMismatch")); @@ -580,52 +580,52 @@ namespace azure { namespace storage { namespace protocol { // This section provides error code strings that are specific to the Queue service. /// - /// Error code that may be returned when the specified queue was not found. + /// The specified queue was not found. /// const utility::string_t error_code_queue_not_found(U("QueueNotFound")); /// - /// Error code that may be returned when the specified queue is disabled. + /// The specified queue is disabled. /// const utility::string_t error_code_queue_disabled(U("QueueDisabled")); /// - /// Error code that may be returned when the specified queue already exists. + /// The specified queue already exists. /// const utility::string_t error_code_queue_already_exists(U("QueueAlreadyExists")); /// - /// Error code that may be returned when the specified queue is not empty. + /// The specified queue is not empty. /// const utility::string_t error_code_queue_not_empty(U("QueueNotEmpty")); /// - /// Error code that may be returned when the specified queue is being deleted. + /// The specified queue is being deleted. /// const utility::string_t error_code_queue_being_deleted(U("QueueBeingDeleted")); /// - /// Error code that may be returned when the specified pop receipt does not match. + /// The specified pop receipt does not match. /// const utility::string_t error_code_pop_receipt_mismatch(U("PopReceiptMismatch")); /// - /// Error code that may be returned when one or more request parameters are invalid. + /// One or more request parameters are invalid. /// const utility::string_t error_code_invalid_parameter(U("InvalidParameter")); /// - /// Error code that may be returned when the specified message was not found. + /// The specified message was not found. /// const utility::string_t error_code_message_not_found(U("MessageNotFound")); /// - /// Error code that may be returned when the specified message is too large. + /// The specified message is too large. /// const utility::string_t error_code_message_too_large(U("MessageTooLarge")); /// - /// Error code that may be returned when the specified marker is invalid. + /// The specified marker is invalid. /// const utility::string_t error_code_invalid_marker(U("InvalidMarker")); diff --git a/Microsoft.WindowsAzure.Storage/includes/was/queue.h b/Microsoft.WindowsAzure.Storage/includes/was/queue.h index 7cae0fb3..58673e6b 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/queue.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/queue.h @@ -113,9 +113,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. queue_permissions(queue_permissions&& other) { *this = std::move(other); @@ -124,7 +124,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. queue_permissions& operator=(queue_permissions&& other) { @@ -185,9 +185,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_queue_message(cloud_queue_message&& other) { *this = std::move(other); @@ -196,7 +196,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_queue_message& operator=(cloud_queue_message&& other) { @@ -367,9 +367,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. queue_request_options(queue_request_options&& other) { *this = std::move(other); @@ -378,7 +378,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. queue_request_options& operator=(queue_request_options&& other) { @@ -400,85 +400,8 @@ namespace azure { namespace storage { } }; - /// - /// Represents a segment of results - /// and provides a continuation token for retrieving additional results. - /// - class queue_result_segment - { - public: - - /// - /// Initializes a new instance of the class. - /// - queue_result_segment() - { - } - -#if defined(_MSC_VER) && _MSC_VER < 1900 - // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, - // have implicitly-declared move constructor and move assignment operator. - - /// - /// Initializes a new instance of the class. - /// - /// A reference to a set of on which to base the new instance. - queue_result_segment(queue_result_segment&& other) - { - *this = std::move(other); - } - - /// - /// Returns a reference to a object. - /// - /// A reference to a set of to use to set properties. - /// A object with properties set. - queue_result_segment& operator=(queue_result_segment&& other) - { - if (this != &other) - { - m_results = std::move(other.m_results); - m_continuation_token = std::move(other.m_continuation_token); - } - return *this; - } -#endif - - /// - /// Gets an enumerable collection of results. - /// - /// An enumerable collection of results. - const std::vector& results() const - { - return m_results; - } - - /// - /// Gets the continuation token used to retrieve the next segment of results. - /// - /// The continuation token. - const azure::storage::continuation_token& continuation_token() const - { - return m_continuation_token; - } - - private: - - void set_results(std::vector results) - { - m_results = std::move(results); - } - - void set_continuation_token(azure::storage::continuation_token token) - { - m_continuation_token = std::move(token); - } - - std::vector m_results; - azure::storage::continuation_token m_continuation_token; - - friend class cloud_queue_client; - }; + typedef result_segment queue_result_segment; + typedef result_iterator queue_result_iterator; /// /// Provides a client-side logical representation of the Windows Azure Queue service. This client is used to configure and execute requests against the Queue service. @@ -536,9 +459,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_queue_client(cloud_queue_client&& other) { *this = std::move(other); @@ -547,7 +470,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_queue_client& operator=(cloud_queue_client&& other) { @@ -560,6 +483,37 @@ namespace azure { namespace storage { } #endif + /// + /// Returns a that can be used to to lazily enumerate a collection of queues. + /// + /// A that can be used to to lazily enumerate a collection of queues. + queue_result_iterator list_queues() const + { + return list_queues(utility::string_t(), false, 0, queue_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of queues that begin with the specified prefix. + /// + /// The queue name prefix. + /// A that can be used to to lazily enumerate a collection of queues. + queue_result_iterator list_queues(const utility::string_t& prefix) const + { + return list_queues(prefix, false, 0, queue_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of queues that begin with the specified prefix. + /// + /// The queue name prefix. + /// A flag that specifies whether to retrieve queue metadata. + /// A non-negative integer value that indicates the maximum number of results to be returned. + /// If this value is zero, the maximum possible number of results will be returned. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. + /// A that can be used to to lazily enumerate a collection of queues. + WASTORAGE_API queue_result_iterator list_queues(const utility::string_t& prefix, bool get_metadata, utility::size64_t max_results, const queue_request_options& options, operation_context context) const; + /// /// Returns a result segment containing a collection of queues in the storage account. /// @@ -567,7 +521,7 @@ namespace azure { namespace storage { /// A result segment containing a collection of queues. queue_result_segment list_queues_segmented(const continuation_token& token) const { - return list_queues_segmented_async(utility::string_t(), false, -1, token, queue_request_options(), operation_context()).get(); + return list_queues_segmented_async(utility::string_t(), false, 0, token, queue_request_options(), operation_context()).get(); } /// @@ -578,7 +532,7 @@ namespace azure { namespace storage { /// A result segment containing a collection of queues. queue_result_segment list_queues_segmented(const utility::string_t& prefix, const continuation_token& token) const { - return list_queues_segmented_async(prefix, false, -1, token, queue_request_options(), operation_context()).get(); + return list_queues_segmented_async(prefix, false, 0, token, queue_request_options(), operation_context()).get(); } /// @@ -586,7 +540,7 @@ namespace azure { namespace storage { /// /// A continuation token returned by a previous listing operation. /// The queue name prefix. - /// A enumeration describing which items to include in the listing. + /// A flag that specifies whether to retrieve queue metadata. /// A non-negative integer value that indicates the maximum number of results to be returned at a time, up to the /// per-operation limit of 5000. If this value is 0, the maximum possible number of results will be returned, up to 5000. /// A object that specifies additional options for the request. @@ -604,7 +558,7 @@ namespace azure { namespace storage { /// A object of type that represents the current operation. pplx::task list_queues_segmented_async(const continuation_token& token) const { - return list_queues_segmented_async(utility::string_t(), false, -1, token, queue_request_options(), operation_context()); + return list_queues_segmented_async(utility::string_t(), false, 0, token, queue_request_options(), operation_context()); } /// @@ -615,7 +569,7 @@ namespace azure { namespace storage { /// A object of type that represents the current operation. pplx::task list_queues_segmented_async(const utility::string_t& prefix, const continuation_token& token) const { - return list_queues_segmented_async(prefix, false, -1, token, queue_request_options(), operation_context()); + return list_queues_segmented_async(prefix, false, 0, token, queue_request_options(), operation_context()); } /// @@ -760,8 +714,6 @@ namespace azure { namespace storage { return m_default_request_options; } - protected: - /// /// Sets the authentication scheme to use to sign HTTP requests. /// @@ -813,9 +765,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_queue(cloud_queue&& other) { *this = std::move(other); @@ -824,7 +776,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_queue& operator=(cloud_queue&& other) { @@ -1592,7 +1544,7 @@ namespace azure { namespace storage { cloud_queue_client m_client; utility::string_t m_name; storage_uri m_uri; - std::shared_ptr m_approximate_message_count; + std::shared_ptr m_approximate_message_count; std::shared_ptr m_metadata; friend class cloud_queue_client; diff --git a/Microsoft.WindowsAzure.Storage/includes/was/service_client.h b/Microsoft.WindowsAzure.Storage/includes/was/service_client.h index 53ce33d4..a52d564a 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/service_client.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/service_client.h @@ -35,9 +35,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_client(cloud_client&& other) { *this = std::move(other); @@ -46,7 +46,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_client& operator=(cloud_client&& other) { diff --git a/Microsoft.WindowsAzure.Storage/includes/was/storage_account.h b/Microsoft.WindowsAzure.Storage/includes/was/storage_account.h index 9cc0db02..131b9b12 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/storage_account.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/storage_account.h @@ -86,9 +86,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_storage_account(cloud_storage_account&& other) { *this = std::move(other); @@ -97,7 +97,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_storage_account& operator=(cloud_storage_account&& other) { diff --git a/Microsoft.WindowsAzure.Storage/includes/was/table.h b/Microsoft.WindowsAzure.Storage/includes/was/table.h index caf14591..d523ffa9 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/table.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/table.h @@ -17,13 +17,13 @@ #pragma once +#include "common.h" #include "service_client.h" namespace azure { namespace storage { class cloud_table; class table_operation; - class table_result_segment; class table_entity; namespace protocol @@ -227,9 +227,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_permissions(table_permissions&& other) { *this = std::move(other); @@ -238,7 +238,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_permissions& operator=(table_permissions&& other) { @@ -271,9 +271,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_request_options(table_request_options&& other) { *this = std::move(other); @@ -282,7 +282,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_request_options& operator=(table_request_options&& other) { @@ -438,9 +438,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. entity_property(entity_property&& other) { *this = std::move(other); @@ -449,7 +449,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. entity_property& operator=(entity_property&& other) { @@ -761,9 +761,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_entity(table_entity&& other) { *this = std::move(other); @@ -772,7 +772,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_entity& operator=(table_entity&& other) { @@ -907,9 +907,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_operation(table_operation&& other) { *this = std::move(other); @@ -918,7 +918,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_operation& operator=(table_operation&& other) { @@ -1058,9 +1058,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_batch_operation(table_batch_operation&& other) { *this = std::move(other); @@ -1069,7 +1069,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_batch_operation& operator=(table_batch_operation&& other) { @@ -1267,9 +1267,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_query(table_query&& other) { *this = std::move(other); @@ -1278,7 +1278,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_query& operator=(table_query&& other) { @@ -1520,9 +1520,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. table_result(table_result&& other) { *this = std::move(other); @@ -1531,7 +1531,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. table_result& operator=(table_result&& other) { @@ -1606,165 +1606,11 @@ namespace azure { namespace storage { utility::string_t m_etag; }; - /// - /// Represents a segment of results. May include a continuation token for - /// retrieving the next page of results. - /// - class table_result_segment - { - public: - - /// - /// Initializes a new instance of the class. - /// - table_result_segment() - { - } - -#if defined(_MSC_VER) && _MSC_VER < 1900 - // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, - // have implicitly-declared move constructor and move assignment operator. - - /// - /// Initializes a new instance of the class. - /// - /// A reference to a set of on which to base the new instance. - table_result_segment(table_result_segment&& other) - { - *this = std::move(other); - } - - /// - /// Returns a reference to a object. - /// - /// A reference to a set of to use to set properties. - /// A object with properties set. - table_result_segment& operator=(table_result_segment&& other) - { - if (this != &other) - { - m_results = std::move(other.m_results); - m_continuation_token = std::move(other.m_continuation_token); - } - return *this; - } -#endif - - /// - /// Gets an enumerable collection of results. - /// - /// An enumerable collection of results. - const std::vector& results() const - { - return m_results; - } - - /// - /// Gets the continuation token to use to retrieve the next segment of results. - /// - /// An object of type . - const azure::storage::continuation_token& continuation_token() const - { - return m_continuation_token; - } - - private: - - void set_results(std::vector results) - { - m_results = std::move(results); - } - - void set_continuation_token(azure::storage::continuation_token token) - { - m_continuation_token = std::move(token); - } - - std::vector m_results; - azure::storage::continuation_token m_continuation_token; - - friend class cloud_table_client; - }; - - /// - /// Represents a segment of results. May include a continuation token for - /// retrieving the next page of results. - /// - class table_query_segment - { - public: - - /// - /// Initializes a new instance of the class. - /// - table_query_segment() - { - } - -#if defined(_MSC_VER) && _MSC_VER < 1900 - // Compilers that fully support C++ 11 rvalue reference, e.g. g++ 4.8+, clang++ 3.3+ and Visual Studio 2015+, - // have implicitly-declared move constructor and move assignment operator. - - /// - /// Initializes a new instance of the class. - /// - /// A reference to a set of on which to base the new instance. - table_query_segment(table_query_segment&& other) - { - *this = std::move(other); - } - - /// - /// Returns a reference to a object. - /// - /// A reference to a set of to use to set properties. - /// A object with properties set. - table_query_segment& operator=(table_query_segment&& other) - { - if (this != &other) - { - m_results = std::move(other.m_results); - m_continuation_token = std::move(other.m_continuation_token); - } - return *this; - } -#endif - - /// - /// Gets an enumerable collection of results. - /// - /// An enumerable collection of results. - const std::vector& results() const - { - return m_results; - } - - /// - /// Gets the continuation token to use to retrieve the next segment of results. - /// - /// An object of type . - const azure::storage::continuation_token& continuation_token() const - { - return m_continuation_token; - } - - private: - - void set_results(std::vector results) - { - m_results = std::move(results); - } - - void set_continuation_token(azure::storage::continuation_token token) - { - m_continuation_token = std::move(token); - } - - std::vector m_results; - azure::storage::continuation_token m_continuation_token; + typedef result_segment table_result_segment; + typedef result_iterator table_result_iterator; - friend class cloud_table; - }; + typedef result_segment table_query_segment; + typedef result_iterator table_query_iterator; /// /// Provides a client-side logical representation of the Windows Azure Table service. @@ -1826,9 +1672,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_table_client(cloud_table_client&& other) { *this = std::move(other); @@ -1837,7 +1683,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_table_client& operator=(cloud_table_client&& other) { @@ -1853,9 +1699,38 @@ namespace azure { namespace storage { /// /// Sets the authentication scheme to use to sign HTTP requests. /// - /// The authentication scheme. + /// An object that specifies the authentication scheme. WASTORAGE_API void set_authentication_scheme(azure::storage::authentication_scheme value) override; + /// + /// Returns a that can be used to to lazily enumerate a collection of tables. + /// + /// A that can be used to to lazily enumerate a collection of tables. + table_result_iterator list_tables() const + { + return list_tables(utility::string_t(), 0, table_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of tables that begin with the specified prefix. + /// + /// A that can be used to to lazily enumerate a collection of tables. + table_result_iterator list_tables(const utility::string_t& prefix) const + { + return list_tables(prefix, 0, table_request_options(), operation_context()); + } + + /// + /// Returns a that can be used to to lazily enumerate a collection of tables that begin with the specified prefix. + /// + /// The table name prefix. + /// A non-negative integer value that indicates the maximum number of results to be returned. + /// If this value is zero, the maximum possible number of results will be returned. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. + /// A that can be used to to lazily enumerate a collection of tables. + WASTORAGE_API table_result_iterator list_tables(const utility::string_t& prefix, utility::size64_t max_results, const table_request_options& options, operation_context context) const; + /// /// Returns a containing an enumerable collection of tables. /// @@ -1867,7 +1742,7 @@ namespace azure { namespace storage { } /// - /// Returns a containing an enumerable collection of tables, retrieved lazily, that begin with the specified prefix. + /// Returns a containing an enumerable collection of tables that begin with the specified prefix. /// /// The table name prefix. /// A returned by a previous listing operation. @@ -1882,7 +1757,7 @@ namespace azure { namespace storage { /// /// The table name prefix. /// A non-negative integer value that indicates the maximum number of results to be returned at a time, up to the - /// per-operation limit of 5000. If this value is zero the maximum possible number of results will be returned, up to 5000. + /// per-operation limit of 1000. If this value is zero the maximum possible number of results will be returned, up to 1000. /// A returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. @@ -1903,7 +1778,7 @@ namespace azure { namespace storage { } /// - /// Intitiates an asynchronous operation that returns a containing an enumerable collection of tables, retrieved lazily, that begin with the specified prefix. + /// Intitiates an asynchronous operation that returns a containing an enumerable collection of tables that begin with the specified prefix. /// /// The table name prefix. /// A returned by a previous listing operation. @@ -1918,7 +1793,7 @@ namespace azure { namespace storage { /// /// The table name prefix. /// A non-negative integer value that indicates the maximum number of results to be returned at a time, up to the - /// per-operation limit of 5000. If this value is zero the maximum possible number of results will be returned, up to 5000. + /// per-operation limit of 1000. If this value is zero the maximum possible number of results will be returned, up to 1000. /// A returned by a previous listing operation. /// A object that specifies additional options for the request. /// An object that represents the context for the current operation. @@ -2102,9 +1977,9 @@ namespace azure { namespace storage { // have implicitly-declared move constructor and move assignment operator. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class based on an existing instance. /// - /// A reference to a set of on which to base the new instance. + /// An existing object. cloud_table(cloud_table&& other) { *this = std::move(other); @@ -2113,7 +1988,7 @@ namespace azure { namespace storage { /// /// Returns a reference to a object. /// - /// A reference to a set of to use to set properties. + /// An existing object to use to set properties. /// A object with properties set. cloud_table& operator=(cloud_table&& other) { @@ -2211,6 +2086,25 @@ namespace azure { namespace storage { /// A object of type , of type , that represents the current operation. WASTORAGE_API pplx::task> execute_batch_async(const table_batch_operation& operation, const table_request_options& options, operation_context context) const; + /// + /// Executes a query on a table. + /// + /// A object. + /// A that can be used to to lazily enumerate a collection of objects. + table_query_iterator execute_query(const table_query& query) const + { + return execute_query(query, table_request_options(), operation_context()); + } + + /// + /// Executes a query on a table. + /// + /// A object. + /// A object that specifies additional options for the request. + /// An object that represents the context for the current operation. This object is used to track requests to the storage service, and to provide additional runtime information about the operation. + /// A that can be used to to lazily enumerate a collection of objects. + WASTORAGE_API table_query_iterator execute_query(const table_query& query, const table_request_options& options, operation_context context) const; + /// /// Executes a query with the specified to retrieve the next page of results. /// diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h b/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h index aa1fbd9a..c5cb8d7f 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h @@ -308,9 +308,9 @@ namespace azure { namespace storage { namespace protocol { // user agent #if defined(WIN32) - const utility::string_t header_value_user_agent(U("Azure-Storage/0.6.0 (Native; Windows)")); + const utility::string_t header_value_user_agent(U("Azure-Storage/1.0.0 (Native; Windows)")); #else - const utility::string_t header_value_user_agent(U("Azure-Storage/0.6.0 (Native)")); + const utility::string_t header_value_user_agent(U("Azure-Storage/1.0.0 (Native)")); #endif }}} // namespace azure::storage::protocol diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp index f4a8812e..2bcb8d2f 100644 --- a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp @@ -65,16 +65,17 @@ namespace azure { namespace storage { namespace samples { azure::storage::continuation_token token; do { - azure::storage::blob_result_segment result = container.list_blobs_segmented(token); - std::vector blobs = result.blobs(); - for (std::vector::const_iterator it = blobs.cbegin(); it != blobs.cend(); ++it) + azure::storage::list_blob_item_segment result = container.list_blobs_segmented(token); + for (auto& item : result.results()) { - ucout << U("Blob: ") << it->uri().primary_uri().to_string() << std::endl; - } - std::vector directories = result.directories(); - for (std::vector::const_iterator it = directories.cbegin(); it != directories.cend(); ++it) - { - ucout << U("Directory: ") << it->uri().primary_uri().to_string() << std::endl; + if (item.is_blob()) + { + ucout << U("Blob: ") << item.as_blob().uri().primary_uri().to_string() << std::endl; + } + else + { + ucout << U("Directory: ") << item.as_directory().uri().primary_uri().to_string() << std::endl; + } } token = result.continuation_token(); } diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.v120.vcxproj b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.v120.vcxproj index 935466be..7f19e81c 100644 --- a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.v120.vcxproj @@ -39,7 +39,7 @@ - ebe55a88 + f39d09a7 true diff --git a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/NativeClientLibraryDemo1.vcxproj b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/NativeClientLibraryDemo1.vcxproj index 64426fdc..8ac3a51d 100644 --- a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/NativeClientLibraryDemo1.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/NativeClientLibraryDemo1.vcxproj @@ -40,7 +40,7 @@ - 0ebdaa86 + 94e665ca true @@ -102,8 +102,8 @@ - - + + @@ -111,7 +111,7 @@ - - + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/packages.config b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/packages.config index ee281a2a..e3165151 100644 --- a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/packages.config +++ b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo1/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.cpp b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.cpp index 32549f75..a89f4ca0 100644 --- a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.cpp +++ b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.cpp @@ -39,8 +39,9 @@ int _tmain(int argc, _TCHAR* argv[]) azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::less_than, end_row_key)) ); - std::vector entities = table.execute_query(query); - for (auto it = entities.cbegin(); it != entities.cend(); ++it) + azure::storage::table_query_iterator it = table.execute_query(query); + azure::storage::table_query_iterator end_of_results; + for (; it != end_of_results; ++it) { ucout << U("Entity: ") << it->row_key() << U(" "); ucout << it->properties().at(U("PostId")).int32_value() << U(" "); diff --git a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.sln b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.sln index aa7254c0..495fb5ce 100644 --- a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.sln +++ b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NativeClientLibraryDemo2", "NativeClientLibraryDemo2.vcxproj", "{9999D237-9C22-4B26-8EE8-66686B47A707}" +Project("{A210F7E6-0DE9-4D39-8B86-5F79C1D8CA7C}") = "NativeClientLibraryDemo2", "NativeClientLibraryDemo2.vcxproj", "{9999D237-9C22-4B26-8EE8-66686B47A707}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.vcxproj b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.vcxproj index b92623f0..a8629788 100644 --- a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/NativeClientLibraryDemo2.vcxproj @@ -40,7 +40,7 @@ - aa87949c + dfadcfd8 true @@ -102,8 +102,8 @@ - - + + @@ -111,7 +111,7 @@ - - + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/packages.config b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/packages.config index ee281a2a..e3165151 100644 --- a/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/packages.config +++ b/Microsoft.WindowsAzure.Storage/samples/Channel9GoingNativeDemo2/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.v120.vcxproj b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.v120.vcxproj index 1395b4f1..88d9d4f6 100644 --- a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.v120.vcxproj @@ -39,7 +39,7 @@ - 26d9641a + 24d1de5a true diff --git a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.v120.vcxproj b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.v120.vcxproj index c882d338..57e19a60 100644 --- a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.v120.vcxproj @@ -39,7 +39,7 @@ - e2d726f4 + c1f9c24e true diff --git a/Microsoft.WindowsAzure.Storage/samples/SamplesCommon/packages.config b/Microsoft.WindowsAzure.Storage/samples/SamplesCommon/packages.config deleted file mode 100644 index 38fd4cb4..00000000 --- a/Microsoft.WindowsAzure.Storage/samples/SamplesCommon/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.v120.vcxproj b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.v120.vcxproj index ea59958b..6028c43c 100644 --- a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.v120.vcxproj @@ -39,7 +39,7 @@ - ab81d08d + 5fd6bf62 true diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp index 85748490..6a827203 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp @@ -594,7 +594,7 @@ namespace azure { namespace storage { pplx::task cloud_blob::start_copy_from_blob_async(const cloud_blob& source, const access_condition& source_condition, const access_condition& destination_condition, const blob_request_options& options, operation_context context) { - const web::http::uri& raw_source_uri = source.snapshot_qualified_uri().primary_uri(); + web::http::uri raw_source_uri = source.snapshot_qualified_uri().primary_uri(); web::http::uri source_uri = service_client().credentials().transform_uri(raw_source_uri); return start_copy_from_blob_async(source_uri, source_condition, destination_condition, options, context); diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp index 530e907e..cd3a8b2c 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp @@ -22,6 +22,17 @@ namespace azure { namespace storage { + container_result_iterator cloud_blob_client::list_containers(const utility::string_t& prefix, container_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const + { + auto instance = std::make_shared(*this); + return container_result_iterator( + [instance, prefix, includes, options, context](const continuation_token& token, size_t max_results_per_segment) + { + return instance->list_containers_segmented(prefix, includes, (int)max_results_per_segment, token, options, context); + }, + max_results, 0); + } + pplx::task cloud_blob_client::list_containers_segmented_async(const utility::string_t& prefix, container_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { blob_request_options modified_options(options); @@ -54,24 +65,24 @@ namespace azure { namespace storage { return core::executor::execute_async(command, modified_options, context); } - pplx::task cloud_blob_client::list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const + list_blob_item_iterator cloud_blob_client::list_blobs(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const + { + utility::string_t container_name; + utility::string_t actual_prefix; + parse_blob_name_prefix(prefix, container_name, actual_prefix); + + auto container = container_name.empty() ? get_root_container_reference() : get_container_reference(container_name); + return container.list_blobs(actual_prefix, use_flat_blob_listing, includes, max_results, options, context); + } + + pplx::task cloud_blob_client::list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { blob_request_options modified_options(options); modified_options.apply_defaults(default_request_options(), blob_type::unspecified); utility::string_t container_name; utility::string_t actual_prefix; - - auto first_slash = prefix.find(U('/')); - if (first_slash == prefix.npos) - { - actual_prefix = prefix; - } - else - { - container_name = prefix.substr(0, first_slash); - actual_prefix = prefix.substr(first_slash + 1); - } + parse_blob_name_prefix(prefix, container_name, actual_prefix); auto container = container_name.empty() ? get_root_container_reference() : get_container_reference(container_name); return container.list_blobs_segmented_async(actual_prefix, use_flat_blob_listing, includes, max_results, token, modified_options, context); @@ -143,4 +154,19 @@ namespace azure { namespace storage { } } + void cloud_blob_client::parse_blob_name_prefix(const utility::string_t& prefix, utility::string_t& container_name, utility::string_t& actual_prefix) + { + auto first_slash = prefix.find(U('/')); + if (first_slash == prefix.npos) + { + container_name = utility::string_t(); + actual_prefix = prefix; + } + else + { + container_name = prefix.substr(0, first_slash); + actual_prefix = prefix.substr(first_slash + 1); + } + } + }} // namespace azure::storage diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp index 360ce31b..78184063 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp @@ -367,7 +367,18 @@ namespace azure { namespace storage { }); } - pplx::task cloud_blob_container::list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const + list_blob_item_iterator cloud_blob_container::list_blobs(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const + { + auto instance = std::make_shared(*this); + return list_blob_item_iterator( + [instance, prefix, use_flat_blob_listing, includes, options, context](const continuation_token& token, size_t max_results_per_segment) + { + return instance->list_blobs_segmented(prefix, use_flat_blob_listing, includes, (int)max_results_per_segment, token, options, context); + }, + max_results, 0); + } + + pplx::task cloud_blob_container::list_blobs_segmented_async(const utility::string_t& prefix, bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { blob_request_options modified_options(options); modified_options.apply_defaults(service_client().default_request_options(), blob_type::unspecified); @@ -385,38 +396,37 @@ namespace azure { namespace storage { delimiter = service_client().directory_delimiter(); } - auto command = std::make_shared>(uri()); + auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::list_blobs, prefix, delimiter, includes, max_results, token, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(core::command_location_mode::primary_or_secondary, token.target_location()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, blob_result_segment(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - command->set_postprocess_response([container, delimiter] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task + command->set_preprocess_response(std::bind(protocol::preprocess_response, list_blob_item_segment(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + command->set_postprocess_response([container, delimiter] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task { protocol::list_blobs_reader reader(response.body()); std::vector blob_items(reader.move_blob_items()); - std::vector blobs; - blobs.reserve(blob_items.size()); + std::vector blob_prefix_items(reader.move_blob_prefix_items()); + + std::vector list_blob_items; + list_blob_items.reserve(blob_items.size() + blob_prefix_items.size()); - for (std::vector::iterator iter = blob_items.begin(); iter != blob_items.end(); ++iter) + for (auto iter = blob_items.begin(); iter != blob_items.end(); ++iter) { - blobs.push_back(cloud_blob(iter->move_name(), iter->move_snapshot_time(), container, iter->move_properties(), iter->move_metadata(), iter->move_copy_state())); + list_blob_items.push_back(list_blob_item(iter->move_name(), iter->move_snapshot_time(), container, iter->move_properties(), iter->move_metadata(), iter->move_copy_state())); } - std::vector blob_prefix_items(reader.move_blob_prefix_items()); - std::vector directories; - directories.reserve(blob_prefix_items.size()); - for (auto iter = blob_prefix_items.begin(); iter != blob_prefix_items.end(); ++iter) { - directories.push_back(cloud_blob_directory(iter->move_name(), container)); + list_blob_items.push_back(list_blob_item(iter->move_name(), container)); } continuation_token next_token(reader.move_next_marker()); next_token.set_target_location(result.target_location()); - return pplx::task_from_result(blob_result_segment(std::move(blobs), std::move(directories), next_token)); + + return pplx::task_from_result(list_blob_item_segment(std::move(list_blob_items), std::move(next_token))); }); - return core::executor::execute_async(command, modified_options, context); + return core::executor::execute_async(command, modified_options, context); } pplx::task cloud_blob_container::upload_permissions_async(const blob_container_permissions& permissions, const access_condition& condition, const blob_request_options& options, operation_context context) diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_directory.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_directory.cpp index 46740242..d9861331 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_directory.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_directory.cpp @@ -82,7 +82,12 @@ namespace azure { namespace storage { } } - pplx::task cloud_blob_directory::list_blobs_segmented_async(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const + list_blob_item_iterator cloud_blob_directory::list_blobs(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const blob_request_options& options, operation_context context) const + { + return m_container.list_blobs(m_name, use_flat_blob_listing, includes, max_results, options, context); + } + + pplx::task cloud_blob_directory::list_blobs_segmented_async(bool use_flat_blob_listing, blob_listing_details::values includes, int max_results, const continuation_token& token, const blob_request_options& options, operation_context context) const { return m_container.list_blobs_segmented_async(m_name, use_flat_blob_listing, includes, max_results, token, options, context); } diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp index 4b149e9e..9dbbfd3b 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp @@ -30,6 +30,17 @@ namespace azure { namespace storage { return modified_options; } + queue_result_iterator cloud_queue_client::list_queues(const utility::string_t& prefix, bool get_metadata, utility::size64_t max_results, const queue_request_options& options, operation_context context) const + { + auto instance = std::make_shared(*this); + return queue_result_iterator( + [instance, prefix, get_metadata, options, context](const continuation_token& token, size_t max_results_per_segment) + { + return instance->list_queues_segmented(prefix, get_metadata, (int)max_results_per_segment, token, options, context); + }, + max_results, 0); + } + pplx::task cloud_queue_client::list_queues_segmented_async(const utility::string_t& prefix, bool get_metadata, int max_results, const continuation_token& token, const queue_request_options& options, operation_context context) const { queue_request_options modified_options = get_modified_options(options); @@ -70,10 +81,7 @@ namespace azure { namespace storage { azure::storage::continuation_token next_token(std::move(next_marker)); next_token.set_target_location(result.target_location()); - queue_result_segment result_segment; - result_segment.set_results(std::move(results)); - result_segment.set_continuation_token(std::move(next_token)); - + queue_result_segment result_segment(std::move(results), std::move(next_token)); return pplx::task_from_result(result_segment); }); return core::executor::execute_async(command, modified_options, context); diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp index 9ca8a6a3..ce578fae 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp @@ -212,6 +212,17 @@ namespace azure { namespace storage { return core::executor>::execute_async(command, modified_options, context); } + table_query_iterator cloud_table::execute_query(const table_query& query, const table_request_options& options, operation_context context) const + { + auto instance = std::make_shared(*this); + return table_query_iterator( + [instance, &query, options, context](const continuation_token& token, size_t) + { + return instance->execute_query_segmented(query, token, options, context); + }, + query.take_count() <= 0 ? 0 : query.take_count(), 0); + } + pplx::task cloud_table::execute_query_segmented_async(const table_query& query, const continuation_token& token, const table_request_options& options, operation_context context) const { table_request_options modified_options = get_modified_options(options); @@ -229,10 +240,7 @@ namespace azure { namespace storage { return response.extract_json().then([next_token] (const web::json::value& obj) -> table_query_segment { - table_query_segment query_segment; - query_segment.set_results(protocol::table_response_parsers::parse_query_results(obj)); - query_segment.set_continuation_token(next_token); - + table_query_segment query_segment(protocol::table_response_parsers::parse_query_results(obj), std::move(next_token)); return query_segment; }); }); diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp index 84339cfe..baf58a75 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp @@ -28,6 +28,17 @@ namespace azure { namespace storage { return modified_options; } + table_result_iterator cloud_table_client::list_tables(const utility::string_t& prefix, utility::size64_t max_results, const table_request_options& options, operation_context context) const + { + auto instance = std::make_shared(*this); + return table_result_iterator( + [instance, prefix, options, context](const continuation_token& token, size_t max_results_per_segment) + { + return instance->list_tables_segmented(prefix, (int)max_results_per_segment, token, options, context); + }, + max_results, 0); + } + pplx::task cloud_table_client::list_tables_segmented_async(const utility::string_t& prefix, int max_results, const continuation_token& token, const table_request_options& options, operation_context context) const { table_request_options modified_options = get_modified_options(options); @@ -70,10 +81,7 @@ namespace azure { namespace storage { table_results.push_back(std::move(current_table)); } - table_result_segment result_segment; - result_segment.set_results(table_results); - result_segment.set_continuation_token(query_segment.continuation_token()); - + table_result_segment result_segment(std::move(table_results), query_segment.continuation_token()); return result_segment; }); } diff --git a/Microsoft.WindowsAzure.Storage/src/hash_windows.cpp b/Microsoft.WindowsAzure.Storage/src/hash_windows.cpp deleted file mode 100644 index 027fcf07..00000000 --- a/Microsoft.WindowsAzure.Storage/src/hash_windows.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// ----------------------------------------------------------------------------------------- -// -// Copyright 2013 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------------------- - -#include "stdafx.h" -#include "wascore/hash_windows.h" - -#ifdef WIN32 - -namespace azure { namespace storage { namespace core { - - class hash_hmac_sha256_algorithm - { - public: - - static const hash_hmac_sha256_algorithm& instance() - { - return m_instance; - } - - ~hash_hmac_sha256_algorithm() - { - BCryptCloseAlgorithmProvider(m_algorithm, 0); - } - - operator BCRYPT_ALG_HANDLE() const - { - return m_algorithm; - } - - private: - - hash_hmac_sha256_algorithm() - { - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algorithm, BCRYPT_SHA256_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG); - if (status != 0) - { - throw utility::details::create_system_error(status); - } - } - - BCRYPT_ALG_HANDLE m_algorithm; - static hash_hmac_sha256_algorithm m_instance; - }; - - hash_hmac_sha256_algorithm hash_hmac_sha256_algorithm::m_instance; - - class hash_md5_algorithm - { - public: - - static const hash_md5_algorithm& instance() - { - return m_instance; - } - - ~hash_md5_algorithm() - { - BCryptCloseAlgorithmProvider(m_algorithm, 0); - } - - operator BCRYPT_ALG_HANDLE() const - { - return m_algorithm; - } - - private: - - hash_md5_algorithm() - { - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algorithm, BCRYPT_MD5_ALGORITHM, NULL, 0); - if (status != 0) - { - throw utility::details::create_system_error(status); - } - } - - BCRYPT_ALG_HANDLE m_algorithm; - static hash_md5_algorithm m_instance; - }; - - hash_md5_algorithm hash_md5_algorithm::m_instance; - - basic_hash_hmac_sha256_streambuf::basic_hash_hmac_sha256_streambuf(const std::vector& key) - { - DWORD hash_object_size = 0; - DWORD data_length = 0; - NTSTATUS status = BCryptGetProperty(hash_hmac_sha256_algorithm::instance(), BCRYPT_OBJECT_LENGTH, (PBYTE)&hash_object_size, sizeof(DWORD), &data_length, 0); - if (status != 0) - { - throw utility::details::create_system_error(status); - } - - m_hash_object.resize(hash_object_size); - status = BCryptCreateHash(hash_hmac_sha256_algorithm::instance(), &m_handle, (PUCHAR)m_hash_object.data(), (ULONG)m_hash_object.size(), (PUCHAR)key.data(), (ULONG)key.size(), 0); - if (status != 0) - { - throw utility::details::create_system_error(status); - } - } - - basic_hash_hmac_sha256_streambuf::~basic_hash_hmac_sha256_streambuf() - { - BCryptDestroyHash(m_handle); - } - - pplx::task basic_hash_hmac_sha256_streambuf::_close_write() - { - DWORD hash_length = 0; - DWORD data_length = 0; - NTSTATUS status = BCryptGetProperty(m_handle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_length, sizeof(DWORD), &data_length, 0); - if (status != 0) - { - store_and_throw(std::make_exception_ptr(utility::details::create_system_error(status))); - } - - m_hash.resize(hash_length); - status = BCryptFinishHash(m_handle, m_hash.data(), (ULONG)m_hash.size(), 0); - if (status != 0) - { - store_and_throw(std::make_exception_ptr(utility::details::create_system_error(status))); - } - - return basic_hash_streambuf::_close_write(); - } - - pplx::task basic_hash_hmac_sha256_streambuf::_putc(basic_hash_hmac_sha256_streambuf::char_type ch) - { - return putn(&ch, 1).then([ch] (size_t count) -> basic_hash_hmac_sha256_streambuf::int_type - { - return count ? (basic_hash_hmac_sha256_streambuf::int_type)ch : traits::eof(); - }); - } - - pplx::task basic_hash_hmac_sha256_streambuf::_putn(const basic_hash_hmac_sha256_streambuf::char_type* ptr, size_t count) - { - NTSTATUS status = BCryptHashData(m_handle, (PBYTE)ptr, (ULONG)count, 0); - if (status != 0) - { - store_and_throw(std::make_exception_ptr(utility::details::create_system_error(status))); - } - - return pplx::task_from_result(count); - } - - basic_hash_md5_streambuf::basic_hash_md5_streambuf() - { - DWORD hash_object_size = 0; - DWORD data_length = 0; - NTSTATUS status = BCryptGetProperty(hash_md5_algorithm::instance(), BCRYPT_OBJECT_LENGTH, (PBYTE)&hash_object_size, sizeof(DWORD), &data_length, 0); - if (status != 0) - { - throw utility::details::create_system_error(status); - } - - m_hash_object.resize(hash_object_size); - status = BCryptCreateHash(hash_md5_algorithm::instance(), &m_handle, (PUCHAR)m_hash_object.data(), (ULONG)m_hash_object.size(), NULL, 0, 0); - if (status != 0) - { - throw utility::details::create_system_error(status); - } - } - - basic_hash_md5_streambuf::~basic_hash_md5_streambuf() - { - BCryptDestroyHash(m_handle); - } - - pplx::task basic_hash_md5_streambuf::_close_write() - { - DWORD hash_length = 0; - DWORD data_length = 0; - NTSTATUS status = BCryptGetProperty(m_handle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_length, sizeof(DWORD), &data_length, 0); - if (status != 0) - { - store_and_throw(std::make_exception_ptr(utility::details::create_system_error(status))); - } - - m_hash.resize(hash_length); - status = BCryptFinishHash(m_handle, m_hash.data(), (ULONG)m_hash.size(), 0); - if (status != 0) - { - store_and_throw(std::make_exception_ptr(utility::details::create_system_error(status))); - } - - return basic_hash_streambuf::_close_write(); - } - - pplx::task basic_hash_md5_streambuf::_putc(basic_hash_md5_streambuf::char_type ch) - { - return putn(&ch, 1).then([ch] (size_t count) -> basic_hash_md5_streambuf::int_type - { - return count ? (basic_hash_md5_streambuf::int_type)ch : traits::eof(); - }); - } - - pplx::task basic_hash_md5_streambuf::_putn(const basic_hash_md5_streambuf::char_type* ptr, size_t count) - { - NTSTATUS status = BCryptHashData(m_handle, (PBYTE)ptr, (ULONG)count, 0); - if (status != 0) - { - store_and_throw(std::make_exception_ptr(utility::details::create_system_error(status))); - } - - return pplx::task_from_result(count); - } - -}}} // namespace azure::storage::core - -#endif // WIN32 diff --git a/Microsoft.WindowsAzure.Storage/src/logging_windows.cpp b/Microsoft.WindowsAzure.Storage/src/logging_windows.cpp deleted file mode 100644 index 9b5f4983..00000000 --- a/Microsoft.WindowsAzure.Storage/src/logging_windows.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// ----------------------------------------------------------------------------------------- -// -// Copyright 2013 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------------------- - -#include "stdafx.h" -#include "wascore/logging.h" - -#include -#include - -namespace azure { namespace storage { namespace core { - - // {EE5D17C5-1B3E-4792-B0F9-F8C5FC6AC22A} - static const GUID event_provider_guid = { 0xee5d17c5, 0x1b3e, 0x4792, { 0xb0, 0xf9, 0xf8, 0xc5, 0xfc, 0x6a, 0xc2, 0x2a } }; - static REGHANDLE g_event_provider_handle; - - UCHAR get_etw_log_level(client_log_level level) - { - switch (level) - { - case client_log_level::log_level_off: - throw std::invalid_argument("level"); - - case client_log_level::log_level_error: - return TRACE_LEVEL_ERROR; - - case client_log_level::log_level_warning: - return TRACE_LEVEL_WARNING; - - case client_log_level::log_level_informational: - return TRACE_LEVEL_INFORMATION; - } - - return TRACE_LEVEL_VERBOSE; - } - - logger::logger() - { - if (EventRegister(&event_provider_guid, NULL, NULL, &g_event_provider_handle) != ERROR_SUCCESS) - { - g_event_provider_handle = NULL; - } - } - - logger::~logger() - { - if (g_event_provider_handle != NULL) - { - EventUnregister(g_event_provider_handle); - } - } - - void logger::log(azure::storage::operation_context context, client_log_level level, const std::string& message) const - { - if (g_event_provider_handle != NULL) - { - utf16string utf16_message = utility::conversions::to_utf16string(message); - EventWriteString(g_event_provider_handle, get_etw_log_level(level), 0, utf16_message.c_str()); - } - } - - void logger::log(azure::storage::operation_context context, client_log_level level, const std::wstring& message) const - { - if (g_event_provider_handle != NULL) - { - EventWriteString(g_event_provider_handle, get_etw_log_level(level), 0, message.c_str()); - } - } - - bool logger::should_log(azure::storage::operation_context context, client_log_level level) const - { - return (g_event_provider_handle != NULL) && (level <= context.log_level()); - } - - logger logger::m_instance; - -}}} // namespace azure::storage::core diff --git a/Microsoft.WindowsAzure.Storage/src/queue_request_factory.cpp b/Microsoft.WindowsAzure.Storage/src/queue_request_factory.cpp index e33f352e..9ce99746 100644 --- a/Microsoft.WindowsAzure.Storage/src/queue_request_factory.cpp +++ b/Microsoft.WindowsAzure.Storage/src/queue_request_factory.cpp @@ -64,7 +64,7 @@ namespace azure { namespace storage { namespace protocol { builder.append_query(core::make_query_parameter(uri_query_include, component_metadata, /* do_encoding */ false)); } - if (max_results >= 0) + if (max_results > 0) { builder.append_query(core::make_query_parameter(uri_query_max_results, max_results, /* do_encoding */ false)); } diff --git a/Microsoft.WindowsAzure.Storage/src/util_windows.cpp b/Microsoft.WindowsAzure.Storage/src/util_windows.cpp deleted file mode 100644 index 27e42975..00000000 --- a/Microsoft.WindowsAzure.Storage/src/util_windows.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// ----------------------------------------------------------------------------------------- -// -// Copyright 2013 Microsoft Corporation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------------------------- - -#include "stdafx.h" -#include "wascore/util.h" -#include "wascore/constants.h" - -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#include - -namespace azure { namespace storage { namespace core { - - pplx::task complete_after(std::chrono::milliseconds timeout) - { - // A task completion event that is set when a timer fires. - pplx::task_completion_event tce; - - // Create a non-repeating timer. - auto fire_once = new concurrency::timer(static_cast(timeout.count()), 0, nullptr, false); - - // Create a call object that sets the completion event after the timer fires. - auto callback = new concurrency::call([tce] (int) - { - tce.set(); - }); - - // Connect the timer to the callback and start the timer. - fire_once->link_target(callback); - fire_once->start(); - - // Create a task that completes after the completion event is set. - pplx::task event_set(tce); - - // Create a continuation task that cleans up resources and - // and return that continuation task. - return event_set.then([callback, fire_once] () - { - delete callback; - delete fire_once; - }); - } - -}}} // namespace azure::storage::core - -#endif diff --git a/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt index 13892551..6959ea9f 100644 --- a/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt +++ b/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt @@ -21,12 +21,14 @@ if(UNIX) main.cpp queue_test_base.cpp read_from_secondary_test.cpp + result_iterator_test.cpp retry_policy_test.cpp service_properties_test.cpp stdafx.cpp storage_exception_test.cpp table_test_base.cpp test_base.cpp + unicode_test.cpp ) endif() diff --git a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj index bb597b42..7a81fbfd 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj @@ -42,7 +42,7 @@ - 228ce23b + 192ed824 true @@ -90,9 +90,6 @@ bcrypt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - @@ -114,6 +111,7 @@ + @@ -131,6 +129,7 @@ + @@ -141,7 +140,7 @@ true false - + {64a4fefe-0461-4e95-8cc1-91ef5f57dbc6} diff --git a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj.filters b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj.filters index 8136dc85..10bfe94e 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj.filters +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj.filters @@ -14,9 +14,6 @@ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - Header Files @@ -116,6 +113,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj index 43dcac44..dc271611 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj @@ -90,9 +90,6 @@ bcrypt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) - - - @@ -114,6 +111,7 @@ + @@ -131,6 +129,7 @@ + @@ -158,7 +157,7 @@ - + diff --git a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj.filters b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj.filters index c291e982..2cd8367f 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj.filters +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj.filters @@ -14,9 +14,6 @@ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - Header Files @@ -116,6 +113,12 @@ Source Files + + Source Files + + + Source Files + diff --git a/Microsoft.WindowsAzure.Storage/tests/README.md b/Microsoft.WindowsAzure.Storage/tests/README.md index 608c38e3..7c0f60e2 100644 --- a/Microsoft.WindowsAzure.Storage/tests/README.md +++ b/Microsoft.WindowsAzure.Storage/tests/README.md @@ -1,3 +1,3 @@ # Unit Tests for Azure Storage Client Library for C++ -Please download [UnitTest++](http://unittest-cpp.sourceforge.net/) and place it into a subfolder named UnitTest++ under this folder. Then add both UnitTest++ and the Microsoft.WindowsAzure.Storage.UnitTests project to the solution to get unit tests working. +Please download [UnitTest++](https://github.com/unittest-cpp/unittest-cpp/tree/sourceforge) and place it into a subfolder named UnitTest++ under this folder. Then add both UnitTest++ project(UnitTest++.vsnet2005.vcproj) and the Microsoft.WindowsAzure.Storage.UnitTests project to the solution to get unit tests working. \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/tests/check_macros.h b/Microsoft.WindowsAzure.Storage/tests/check_macros.h index d537145d..0db3330b 100644 --- a/Microsoft.WindowsAzure.Storage/tests/check_macros.h +++ b/Microsoft.WindowsAzure.Storage/tests/check_macros.h @@ -18,3 +18,27 @@ #pragma once #define CHECK_UTF8_EQUAL(expected, actual) CHECK_EQUAL(utility::conversions::to_utf8string(expected), utility::conversions::to_utf8string(actual)) + +#define CHECK_STORAGE_EXCEPTION(expression, expected_message) \ + do \ + { \ + bool caught_ = false; \ + std::string returned_message; \ + try { expression; } \ + catch (const azure::storage::storage_exception& ex) { \ + returned_message = ex.what(); \ + caught_ = true; \ + } \ + catch (...) {} \ + if (!caught_) \ + UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), "storage_exception not thrown"); \ + else { \ + try { \ + UnitTest::CheckEqual(*UnitTest::CurrentTest::Results(), expected_message, returned_message, UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__)); \ + } \ + catch (...) { \ + UnitTest::CurrentTest::Results()->OnTestFailure(UnitTest::TestDetails(*UnitTest::CurrentTest::Details(), __LINE__), \ + "Unhandled exception in CHECK_STORAGE_EXCEPTION"); \ + } \ + } \ + } while(0) diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp index ed1b8abc..0d1ce0f9 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp @@ -104,23 +104,14 @@ void blob_service_test_base_with_objects_to_delete::check_blob_list(const std::v std::vector blob_service_test_base::list_all_containers(const utility::string_t& prefix, azure::storage::container_listing_details::values includes, int max_results, const azure::storage::blob_request_options& options) { - std::vector containers; - azure::storage::continuation_token token; - - do + std::vector results; + azure::storage::container_result_iterator end_of_result; + for (azure::storage::container_result_iterator iter = m_client.list_containers(prefix, includes, max_results, options, m_context); iter != end_of_result; ++iter) { - auto results = m_client.list_containers_segmented(prefix, includes, max_results, token, options, m_context); - - if (max_results > 0) - { - CHECK(results.results().size() <= static_cast(max_results)); - } - - std::copy(results.results().begin(), results.results().end(), std::back_inserter(containers)); - token = results.continuation_token(); - } while (!token.empty()); + results.push_back(*iter); + } - return containers; + return results; } std::vector blob_service_test_base::list_all_blobs_from_client(const utility::string_t& prefix, azure::storage::blob_listing_details::values includes, int max_results, const azure::storage::blob_request_options& options) @@ -134,10 +125,18 @@ std::vector blob_service_test_base::list_all_blobs_f if (max_results > 0) { - CHECK(results.blobs().size() <= static_cast(max_results)); + CHECK(results.results().size() <= static_cast(max_results)); + } + + blobs.reserve(results.results().size()); + for (auto& item : results.results()) + { + if (item.is_blob()) + { + blobs.push_back(std::move(item.as_blob())); + } } - std::copy(results.blobs().begin(), results.blobs().end(), std::back_inserter(blobs)); token = results.continuation_token(); } while (!token.empty()); @@ -191,10 +190,18 @@ SUITE(Blob) TEST_FIXTURE(blob_service_test_base_with_objects_to_delete, list_containers_with_continuation_token) { auto prefix = get_random_container_name(); - create_containers(prefix, 10); - auto listing = list_all_containers(prefix, azure::storage::container_listing_details::all, 3, azure::storage::blob_request_options()); + std::vector listing; + azure::storage::continuation_token token; + azure::storage::blob_request_options options; + do{ + auto results = m_client.list_containers_segmented(prefix, azure::storage::container_listing_details::all, 3, token, options, m_context); + CHECK(results.results().size() <= 3); + + std::copy(results.results().begin(), results.results().end(), std::back_inserter(listing)); + token = results.continuation_token(); + } while (!token.empty()); check_container_list(listing, prefix, true); } @@ -218,7 +225,10 @@ SUITE(Blob) std::vector blobs; auto prefix = get_random_container_name(); - for (int i = 0; i < 1; i++) + std::vector blobs2; + auto prefix2 = get_random_container_name(); + + for (int i = 0; i < 3; i++) { auto index = utility::conversions::print_string(i); auto blob = m_container.get_block_blob_reference(prefix + index); @@ -226,42 +236,53 @@ SUITE(Blob) blobs.push_back(blob); } - std::vector original_blobs(blobs); + for (int i = 0; i < 2; i++) + { + auto index = utility::conversions::print_string(i); + auto blob = m_container.get_block_blob_reference(prefix2 + index); + blob.upload_text(U("test2"), azure::storage::access_condition(), azure::storage::blob_request_options(), m_context); + blobs2.push_back(blob); + } + + std::vector all_blobs(blobs); + all_blobs.insert(all_blobs.end(), blobs2.begin(), blobs2.end()); - auto listing = list_all_blobs_from_client(m_container.name(), azure::storage::blob_listing_details::none, 1, azure::storage::blob_request_options()); + auto listing = list_all_blobs_from_client(m_container.name(), azure::storage::blob_listing_details::none, 0, azure::storage::blob_request_options()); CHECK(listing.empty()); - listing = list_all_blobs_from_client(m_container.name() + U("/"), azure::storage::blob_listing_details::none, 1, azure::storage::blob_request_options()); + listing = list_all_blobs_from_client(m_container.name() + U("/"), azure::storage::blob_listing_details::none, 0, azure::storage::blob_request_options()); + CHECK_EQUAL(5U, listing.size()); for (auto listing_iter = listing.begin(); listing_iter != listing.end(); ++listing_iter) { - for (auto iter = blobs.begin(); iter != blobs.end(); ++iter) + for (auto iter = all_blobs.begin(); iter != all_blobs.end(); ++iter) { if (iter->name() == listing_iter->name()) { - blobs.erase(iter); + all_blobs.erase(iter); break; } } } - CHECK(blobs.empty()); + CHECK(all_blobs.empty()); - blobs = original_blobs; + std::vector blobs_copy(blobs); - listing = list_all_blobs_from_client(m_container.name() + U("/") + prefix, azure::storage::blob_listing_details::none, 1, azure::storage::blob_request_options()); + listing = list_all_blobs_from_client(m_container.name() + U("/") + prefix, azure::storage::blob_listing_details::none, 0, azure::storage::blob_request_options()); + CHECK_EQUAL(3U, listing.size()); for (auto listing_iter = listing.begin(); listing_iter != listing.end(); ++listing_iter) { - for (auto iter = blobs.begin(); iter != blobs.end(); ++iter) + for (auto iter = blobs_copy.begin(); iter != blobs_copy.end(); ++iter) { if (iter->name() == listing_iter->name()) { - blobs.erase(iter); + blobs_copy.erase(iter); break; } } } - CHECK(blobs.empty()); + CHECK(blobs_copy.empty()); } TEST_FIXTURE(test_base, blob_shared_key_lite) diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_container_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_container_test.cpp index c03de01a..6180b945 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_container_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_container_test.cpp @@ -56,20 +56,15 @@ void container_test_base::check_public_access(azure::storage::blob_container_pub std::vector container_test_base::list_all_blobs(const utility::string_t& prefix, azure::storage::blob_listing_details::values includes, int max_results, const azure::storage::blob_request_options& options) { std::vector blobs; - azure::storage::continuation_token token; - - do + azure::storage::list_blob_item_iterator end_of_result; + auto iter = m_container.list_blobs(prefix, true, includes, max_results, options, m_context); + for (; iter != end_of_result; ++iter) { - auto results = m_container.list_blobs_segmented(prefix, true, includes, max_results, token, options, m_context); - - if (max_results > 0) + if (iter->is_blob()) { - CHECK(results.blobs().size() <= static_cast(max_results)); + blobs.push_back(iter->as_blob()); } - - std::copy(results.blobs().begin(), results.blobs().end(), std::back_inserter(blobs)); - token = results.continuation_token(); - } while (!token.empty()); + } return blobs; } @@ -207,7 +202,7 @@ SUITE(Blob) blobs[blob.name()] = blob; } - auto listing1 = list_all_blobs(utility::string_t(), azure::storage::blob_listing_details::all, 2, azure::storage::blob_request_options()); + auto listing1 = list_all_blobs(utility::string_t(), azure::storage::blob_listing_details::all, 0, azure::storage::blob_request_options()); for (auto iter = listing1.begin(); iter != listing1.end(); ++iter) { auto blob = blobs.find(iter->name()); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_directory_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_directory_test.cpp index cffe70c7..cc5a637f 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_directory_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_directory_test.cpp @@ -79,17 +79,22 @@ int list_entire_blob_tree_helper(std::vector& blobs, if (max_results > 0) { - CHECK((results.blobs().size() + results.directories().size()) <= static_cast(max_results)); + CHECK(results.results().size() <= static_cast(max_results)); } - std::copy(results.blobs().begin(), results.blobs().end(), std::back_inserter(blobs)); - - for (auto iter = results.directories().begin(); iter != results.directories().end(); ++iter) + for (auto& item : results.results()) { - int depth = list_entire_blob_tree_helper(blobs, *iter, includes, max_results, options, context); - if (depth > max_depth) + if (item.is_blob()) + { + blobs.push_back(std::move(item.as_blob())); + } + else { - max_depth = depth; + int depth = list_entire_blob_tree_helper(blobs, item.as_directory(), includes, max_results, options, context); + if (depth > max_depth) + { + max_depth = depth; + } } } @@ -111,17 +116,22 @@ std::vector list_entire_blob_tree(const azure::stora if (max_results > 0) { - CHECK((results.blobs().size() + results.directories().size()) <= static_cast(max_results)); + CHECK(results.results().size() <= static_cast(max_results)); } - std::copy(results.blobs().begin(), results.blobs().end(), std::back_inserter(blobs)); - - for (auto iter = results.directories().begin(); iter != results.directories().end(); ++iter) + for (auto& item : results.results()) { - int depth = list_entire_blob_tree_helper(blobs, *iter, includes, max_results, options, context); - if (depth > max_depth) + if (item.is_blob()) + { + blobs.push_back(std::move(item.as_blob())); + } + else { - max_depth = depth; + int depth = list_entire_blob_tree_helper(blobs, item.as_directory(), includes, max_results, options, context); + if (depth > max_depth) + { + max_depth = depth; + } } } diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp index 1dbdc200..e1b22d80 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp @@ -397,7 +397,7 @@ SUITE(Blob) policy.set_expiry(utility::datetime::utc_now() + utility::datetime::from_minutes(30)); auto sas_token = m_container.get_shared_access_signature(policy); - auto blob = m_container.get_block_blob_reference(U("blob") + utility::conversions::print_string(i)); + auto blob = m_container.get_block_blob_reference(U("blob") + utility::conversions::print_string((int)i)); blob.properties().set_cache_control(U("no-transform")); blob.properties().set_content_disposition(U("attachment")); blob.properties().set_content_encoding(U("gzip")); @@ -420,7 +420,7 @@ SUITE(Blob) policy.set_start(utility::datetime::utc_now() - utility::datetime::from_minutes(5)); policy.set_expiry(utility::datetime::utc_now() + utility::datetime::from_minutes(30)); - auto blob = m_container.get_block_blob_reference(U("blob") + utility::conversions::print_string(i)); + auto blob = m_container.get_block_blob_reference(U("blob") + utility::conversions::print_string((int)i)); blob.properties().set_cache_control(U("no-transform")); blob.properties().set_content_disposition(U("attachment")); blob.properties().set_content_encoding(U("gzip")); @@ -580,7 +580,10 @@ SUITE(Blob) CHECK_EQUAL(web::http::status_codes::Conflict, m_context.request_results().back().http_status_code()); CHECK_THROW(copy.start_copy_from_blob(defiddler(blob.uri().primary_uri()), azure::storage::access_condition::generate_if_match_condition(blob.properties().etag()), azure::storage::access_condition::generate_if_match_condition(U("\"0xFFFFFFFFFFFFFFF\"")), azure::storage::blob_request_options(), m_context), azure::storage::storage_exception); CHECK_EQUAL(web::http::status_codes::PreconditionFailed, m_context.request_results().back().http_status_code()); - copy.start_copy_from_blob(defiddler(blob.uri().primary_uri()), azure::storage::access_condition::generate_if_match_condition(blob.properties().etag()), azure::storage::access_condition::generate_if_match_condition(copy.properties().etag()), azure::storage::blob_request_options(), m_context); - CHECK(wait_for_copy(copy)); + + auto copy2 = m_container.get_block_blob_reference(U("copy2")); + copy2.start_copy_from_blob(blob, azure::storage::access_condition::generate_if_match_condition(blob.properties().etag()), azure::storage::access_condition(), azure::storage::blob_request_options(), m_context); + CHECK(wait_for_copy(copy2)); + CHECK_THROW(copy2.start_copy_from_blob(blob, azure::storage::access_condition::generate_if_match_condition(blob.properties().etag()), azure::storage::access_condition::generate_if_match_condition(U("\"0xFFFFFFFFFFFFFFF\"")), azure::storage::blob_request_options(), m_context), azure::storage::storage_exception); } } diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp index 190ad583..4e0b7413 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp @@ -26,15 +26,11 @@ std::vector < azure::storage::cloud_queue> list_all_queues( const azure::storage::queue_request_options& options, azure::storage::operation_context context) { std::vector results; - - int max_results_per_segment = 5000; - azure::storage::continuation_token token; - do + azure::storage::queue_result_iterator end_of_result; + for (azure::storage::queue_result_iterator iter = queue_client.list_queues(prefix, get_metadata, 0, options, context); iter != end_of_result; ++iter) { - azure::storage::queue_result_segment result_segment = queue_client.list_queues_segmented(prefix, get_metadata, max_results_per_segment, token, options, context); - results.insert(results.end(), result_segment.results().begin(), result_segment.results().end()); - token = result_segment.continuation_token(); - } while (!token.empty()); + results.push_back(*iter); + } return results; } @@ -93,6 +89,22 @@ SUITE(QueueClient) CHECK(client.default_request_options().location_mode() == azure::storage::location_mode::secondary_only); } + TEST_FIXTURE(queue_service_test_base, QueueClient_MoveConstructor) + { + azure::storage::storage_uri base_uri(web::http::uri(U("https://myaccount.queue.core.windows.net")), web::http::uri(U("https://myaccount-secondary.queue.core.windows.net"))); + azure::storage::storage_credentials credentials(U("devstoreaccount1"), U("Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")); + azure::storage::queue_request_options default_request_options; + default_request_options.set_location_mode(azure::storage::location_mode::secondary_only); + + azure::storage::cloud_queue_client client(base_uri, credentials, default_request_options); + azure::storage::cloud_queue_client client2 = std::move(client); + + CHECK(client2.base_uri().primary_uri() == base_uri.primary_uri()); + CHECK(client2.base_uri().secondary_uri() == base_uri.secondary_uri()); + CHECK(client2.credentials().is_shared_key()); + CHECK(client2.default_request_options().location_mode() == azure::storage::location_mode::secondary_only); + } + TEST_FIXTURE(queue_service_test_base, ListQueues_Normal) { const int QUEUE_COUNT = 5; @@ -306,6 +318,28 @@ SUITE(QueueClient) { CHECK(is_found[i]); } + } + + TEST_FIXTURE(queue_service_test_base, ListQueues_SharedKeyLite) + { + const int QUEUE_COUNT = 5; + azure::storage::cloud_queue queues[QUEUE_COUNT]; + for (int i = 0; i < QUEUE_COUNT; ++i) + { + azure::storage::cloud_queue queue = get_queue(); + queues[i] = queue; + } + + azure::storage::cloud_queue_client client = get_queue_client(); + client.set_authentication_scheme(azure::storage::authentication_scheme::shared_key_lite); + + { + utility::string_t prefix = object_name_prefix; + azure::storage::queue_request_options options; + azure::storage::operation_context context; + std::vector results = list_all_queues(client, prefix, false, options, context); + CHECK(results.size() >= QUEUE_COUNT); + } for (int i = 0; i < QUEUE_COUNT; ++i) { diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp index dad3cc2d..dd01ae31 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_storage_account_test.cpp @@ -41,7 +41,7 @@ void check_credentials_equal(const azure::storage::storage_credentials& a, const CHECK_UTF8_EQUAL(utility::conversions::to_base64(a.account_key()), utility::conversions::to_base64(b.account_key())); } -void check_account_equal(azure::storage::cloud_storage_account a, azure::storage::cloud_storage_account b) +void check_account_equal(azure::storage::cloud_storage_account& a, azure::storage::cloud_storage_account& b) { CHECK_UTF8_EQUAL(a.blob_endpoint().primary_uri().to_string(), b.blob_endpoint().primary_uri().to_string()); CHECK_UTF8_EQUAL(a.blob_endpoint().secondary_uri().to_string(), b.blob_endpoint().secondary_uri().to_string()); @@ -58,7 +58,9 @@ void check_string_roundtrip(const utility::string_t& connection_string) { auto account = azure::storage::cloud_storage_account::parse(connection_string); CHECK_UTF8_EQUAL(connection_string, account.to_string(true)); - check_account_equal(account, azure::storage::cloud_storage_account::parse(account.to_string(true))); + + auto account2 = azure::storage::cloud_storage_account::parse(account.to_string(true)); + check_account_equal(account, account2); } SUITE(Core) @@ -145,6 +147,18 @@ SUITE(Core) check_credentials_equal(creds, account2.credentials()); } + TEST_FIXTURE(test_base, storage_credentials_move_constructor) + { + azure::storage::storage_credentials creds(test_account_name, test_account_key); + azure::storage::storage_credentials creds2 = std::move(creds); + + CHECK(creds2.sas_token().empty()); + CHECK_UTF8_EQUAL(test_account_name, creds2.account_name()); + CHECK_EQUAL(false, creds2.is_anonymous()); + CHECK_EQUAL(false, creds2.is_sas()); + CHECK_EQUAL(true, creds2.is_shared_key()); + } + TEST_FIXTURE(test_base, cloud_storage_account_devstore) { auto account = azure::storage::cloud_storage_account::development_storage_account(); @@ -200,6 +214,15 @@ SUITE(Core) CHECK_UTF8_EQUAL(U("http://") + test_account_name + U("-secondary.blob.") + test_endpoint_suffix + U("/"), account.blob_endpoint().secondary_uri().to_string()); CHECK_UTF8_EQUAL(U("http://") + test_account_name + U("-secondary.queue.") + test_endpoint_suffix + U("/"), account.queue_endpoint().secondary_uri().to_string()); CHECK_UTF8_EQUAL(U("http://") + test_account_name + U("-secondary.table.") + test_endpoint_suffix + U("/"), account.table_endpoint().secondary_uri().to_string()); + + azure::storage::storage_credentials creds(test_account_name, test_account_key); + azure::storage::cloud_storage_account account2(creds, test_endpoint_suffix, false); + CHECK_UTF8_EQUAL(U("http://") + test_account_name + U(".blob.") + test_endpoint_suffix + U("/"), account2.blob_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(U("http://") + test_account_name + U(".queue.") + test_endpoint_suffix + U("/"), account2.queue_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(U("http://") + test_account_name + U(".table.") + test_endpoint_suffix + U("/"), account2.table_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(U("http://") + test_account_name + U("-secondary.blob.") + test_endpoint_suffix + U("/"), account2.blob_endpoint().secondary_uri().to_string()); + CHECK_UTF8_EQUAL(U("http://") + test_account_name + U("-secondary.queue.") + test_endpoint_suffix + U("/"), account2.queue_endpoint().secondary_uri().to_string()); + CHECK_UTF8_EQUAL(U("http://") + test_account_name + U("-secondary.table.") + test_endpoint_suffix + U("/"), account2.table_endpoint().secondary_uri().to_string()); } TEST_FIXTURE(test_base, cloud_storage_account_endpoint_suffix_https) @@ -214,6 +237,15 @@ SUITE(Core) CHECK_UTF8_EQUAL(U("https://") + test_account_name + U("-secondary.blob.") + test_endpoint_suffix + U("/"), account.blob_endpoint().secondary_uri().to_string()); CHECK_UTF8_EQUAL(U("https://") + test_account_name + U("-secondary.queue.") + test_endpoint_suffix + U("/"), account.queue_endpoint().secondary_uri().to_string()); CHECK_UTF8_EQUAL(U("https://") + test_account_name + U("-secondary.table.") + test_endpoint_suffix + U("/"), account.table_endpoint().secondary_uri().to_string()); + + azure::storage::storage_credentials creds(test_account_name, test_account_key); + azure::storage::cloud_storage_account account2(creds, test_endpoint_suffix, true); + CHECK_UTF8_EQUAL(U("https://") + test_account_name + U(".blob.") + test_endpoint_suffix + U("/"), account2.blob_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(U("https://") + test_account_name + U(".queue.") + test_endpoint_suffix + U("/"), account2.queue_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(U("https://") + test_account_name + U(".table.") + test_endpoint_suffix + U("/"), account2.table_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(U("https://") + test_account_name + U("-secondary.blob.") + test_endpoint_suffix + U("/"), account2.blob_endpoint().secondary_uri().to_string()); + CHECK_UTF8_EQUAL(U("https://") + test_account_name + U("-secondary.queue.") + test_endpoint_suffix + U("/"), account2.queue_endpoint().secondary_uri().to_string()); + CHECK_UTF8_EQUAL(U("https://") + test_account_name + U("-secondary.table.") + test_endpoint_suffix + U("/"), account2.table_endpoint().secondary_uri().to_string()); } TEST_FIXTURE(test_base, cloud_storage_account_string_roundtrip) @@ -250,13 +282,36 @@ SUITE(Core) CHECK_UTF8_EQUAL(account.blob_endpoint().primary_uri().to_string(), blob_client.base_uri().primary_uri().to_string()); CHECK_UTF8_EQUAL(account.blob_endpoint().secondary_uri().to_string(), blob_client.base_uri().secondary_uri().to_string()); + azure::storage::blob_request_options blob_options; + blob_options.set_parallelism_factor(10); + blob_options.set_single_blob_upload_threshold_in_bytes(4 * 1024 * 1024); + auto blob_client2 = account.create_cloud_blob_client(blob_options); + CHECK_UTF8_EQUAL(account.blob_endpoint().primary_uri().to_string(), blob_client2.base_uri().primary_uri().to_string()); + CHECK_UTF8_EQUAL(account.blob_endpoint().secondary_uri().to_string(), blob_client2.base_uri().secondary_uri().to_string()); + CHECK_EQUAL(10, blob_client2.default_request_options().parallelism_factor()); + CHECK_EQUAL(4 * 1024 * 1024, blob_client2.default_request_options().single_blob_upload_threshold_in_bytes()); + auto queue_client = account.create_cloud_queue_client(); CHECK_UTF8_EQUAL(account.queue_endpoint().primary_uri().to_string(), queue_client.base_uri().primary_uri().to_string()); CHECK_UTF8_EQUAL(account.queue_endpoint().secondary_uri().to_string(), queue_client.base_uri().secondary_uri().to_string()); + azure::storage::queue_request_options queue_options; + queue_options.set_location_mode(azure::storage::location_mode::secondary_only); + auto queue_client2 = account.create_cloud_queue_client(queue_options); + CHECK_UTF8_EQUAL(account.queue_endpoint().primary_uri().to_string(), queue_client2.base_uri().primary_uri().to_string()); + CHECK_UTF8_EQUAL(account.queue_endpoint().secondary_uri().to_string(), queue_client2.base_uri().secondary_uri().to_string()); + CHECK(azure::storage::location_mode::secondary_only == queue_client2.default_request_options().location_mode()); + auto table_client = account.create_cloud_table_client(); CHECK_UTF8_EQUAL(account.table_endpoint().primary_uri().to_string(), table_client.base_uri().primary_uri().to_string()); CHECK_UTF8_EQUAL(account.table_endpoint().secondary_uri().to_string(), table_client.base_uri().secondary_uri().to_string()); + + azure::storage::table_request_options table_options; + table_options.set_payload_format(azure::storage::table_payload_format::json_full_metadata); + auto table_client2 = account.create_cloud_table_client(table_options); + CHECK_UTF8_EQUAL(account.table_endpoint().primary_uri().to_string(), table_client2.base_uri().primary_uri().to_string()); + CHECK_UTF8_EQUAL(account.table_endpoint().secondary_uri().to_string(), table_client2.base_uri().secondary_uri().to_string()); + CHECK(azure::storage::table_payload_format::json_full_metadata == table_client2.default_request_options().payload_format()); } TEST_FIXTURE(test_base, cloud_storage_account_incorrect_devstore) @@ -266,11 +321,86 @@ SUITE(Core) CHECK_THROW(azure::storage::cloud_storage_account::parse(U("UseDevelopmentStorage=true;BlobEndpoint=http://127.0.0.1:1000/devstoreaccount1")), std::invalid_argument); } - TEST_FIXTURE(test_base, cloud_storage_account_blob_endpoint) + TEST_FIXTURE(test_base, cloud_storage_account_endpoints_in_connection_string) { - auto account = azure::storage::cloud_storage_account::parse(U("DefaultEndpointsProtocol=http;BlobEndpoint=http://customdomain.com/;AccountName=asdf;AccountKey=abc=")); - CHECK_UTF8_EQUAL(U("http://customdomain.com/"), account.blob_endpoint().primary_uri().to_string()); - CHECK(account.blob_endpoint().secondary_uri().is_empty()); + const utility::string_t default_endpoint_suffix(U("core.windows.net")); + utility::string_t endpoints[] = { + U("http://customdomain.com/"), + U("http://customdomain2.com/"), + U("http://customdomain3.com/") }; + + utility::string_t scheme(U("http")); + utility::string_t account_name(U("asdf")); + utility::string_t account_key(U("abc=")); + + for (int i = 1; i < 8; i++) { + utility::ostringstream_t str; + str << U("DefaultEndpointsProtocol=") << scheme << ";"; + if (i & 1) str << U("BlobEndpoint=") << endpoints[0] << ";"; + if (i & 2) str << U("QueueEndpoint=") << endpoints[1] << ";"; + if (i & 4) str << U("TableEndpoint=") << endpoints[2] << ";"; + str << U("AccountName=") << account_name << ";"; + str << U("AccountKey=") << account_key; + + auto account = azure::storage::cloud_storage_account::parse(str.str()); + if (i & 1) { + CHECK_UTF8_EQUAL(endpoints[0], account.blob_endpoint().primary_uri().to_string()); + CHECK(account.blob_endpoint().secondary_uri().is_empty()); + } + else { + CHECK_UTF8_EQUAL(scheme + U("://") + account_name + U(".blob.") + default_endpoint_suffix + U("/"), account.blob_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(scheme + U("://") + account_name + U("-secondary.blob.") + default_endpoint_suffix + U("/"), account.blob_endpoint().secondary_uri().to_string()); + } + + if (i & 2) { + CHECK_UTF8_EQUAL(endpoints[1], account.queue_endpoint().primary_uri().to_string()); + CHECK(account.queue_endpoint().secondary_uri().is_empty()); + } + else { + CHECK_UTF8_EQUAL(scheme + U("://") + account_name + U(".queue.") + default_endpoint_suffix + U("/"), account.queue_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(scheme + U("://") + account_name + U("-secondary.queue.") + default_endpoint_suffix + U("/"), account.queue_endpoint().secondary_uri().to_string()); + } + + if (i & 4) { + CHECK_UTF8_EQUAL(endpoints[2], account.table_endpoint().primary_uri().to_string()); + CHECK(account.table_endpoint().secondary_uri().is_empty()); + } + else { + CHECK_UTF8_EQUAL(scheme + U("://") + account_name + U(".table.") + default_endpoint_suffix + U("/"), account.table_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(scheme + U("://") + account_name + U("-secondary.table.") + default_endpoint_suffix + U("/"), account.table_endpoint().secondary_uri().to_string()); + } + } + } + + TEST_FIXTURE(test_base, cloud_storage_account_endpoints_in_ctor) + { + const int COUNT = 2; + azure::storage::storage_credentials creds(test_account_name, test_account_key); + azure::storage::storage_uri blob_uris[] = { azure::storage::storage_uri(U("http://customdomain.com/")), azure::storage::storage_uri() }; + azure::storage::storage_uri queue_uris[] = { azure::storage::storage_uri(U("http://customdomain2.com/")), azure::storage::storage_uri() }; + azure::storage::storage_uri table_uris[] = { azure::storage::storage_uri(U("http://customdomain3.com/")), azure::storage::storage_uri() }; + + for (int i = 0; i < COUNT; ++i) { + for (int j = 0; j < COUNT; ++j) { + for (int k = 0; k < COUNT; ++k) { + azure::storage::cloud_storage_account account(creds, blob_uris[i], queue_uris[j], table_uris[k]); + CHECK_UTF8_EQUAL(blob_uris[i].primary_uri().to_string(), account.blob_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(queue_uris[j].primary_uri().to_string(), account.queue_endpoint().primary_uri().to_string()); + CHECK_UTF8_EQUAL(table_uris[k].primary_uri().to_string(), account.table_endpoint().primary_uri().to_string()); + + if (i == COUNT - 1 && j == COUNT - 1 && k == COUNT - 1) + { + // all endpoints are empty + CHECK_THROW(azure::storage::cloud_storage_account::parse(account.to_string(true)), std::invalid_argument); + } + else + { + azure::storage::cloud_storage_account account2 = azure::storage::cloud_storage_account::parse(account.to_string(true)); + check_account_equal(account, account2); + } + } + } + } } TEST_FIXTURE(test_base, cloud_storage_account_devstore_proxy) diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp index 3ac856ab..0dff6791 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp @@ -26,15 +26,11 @@ std::vector list_all_tables( azure::storage::operation_context context) { std::vector results; - - int max_results_per_segment = 1000; - azure::storage::continuation_token token; - do + azure::storage::table_result_iterator end_of_result; + for (azure::storage::table_result_iterator iter = table_client.list_tables(prefix, 0, options, context); iter != end_of_result; ++iter) { - azure::storage::table_result_segment result_segment = table_client.list_tables_segmented(prefix, max_results_per_segment, token, options, context); - results.insert(results.end(), result_segment.results().begin(), result_segment.results().end()); - token = result_segment.continuation_token(); - } while (!token.empty()); + results.push_back(*iter); + } return results; } @@ -97,6 +93,22 @@ SUITE(TableClient) CHECK(client.default_request_options().payload_format() == azure::storage::table_payload_format::json_no_metadata); } + TEST_FIXTURE(table_service_test_base, TableClient_MoveConstructor) + { + azure::storage::storage_uri base_uri(web::http::uri(U("https://myaccount.table.core.windows.net")), web::http::uri(U("https://myaccount-secondary.table.core.windows.net"))); + azure::storage::storage_credentials credentials(U("devstoreaccount1"), U("Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==")); + azure::storage::table_request_options default_request_options; + default_request_options.set_payload_format(azure::storage::table_payload_format::json_no_metadata); + + azure::storage::cloud_table_client client(base_uri, credentials, default_request_options); + azure::storage::cloud_table_client client2 = std::move(client); + + CHECK(client2.base_uri().primary_uri() == base_uri.primary_uri()); + CHECK(client2.base_uri().secondary_uri() == base_uri.secondary_uri()); + CHECK(client2.credentials().is_shared_key()); + CHECK(client2.default_request_options().payload_format() == azure::storage::table_payload_format::json_no_metadata); + } + TEST_FIXTURE(table_service_test_base, ListTables_Normal) { const int TABLE_COUNT = 5; @@ -249,4 +261,28 @@ SUITE(TableClient) tables[i].delete_table(); } } + + TEST_FIXTURE(table_service_test_base, ListTabled_SharedKeyLite) + { + const int TABLE_COUNT = 5; + azure::storage::cloud_table tables[TABLE_COUNT]; + for (int i = 0; i < TABLE_COUNT; ++i) + { + tables[i] = get_table(); + } + + azure::storage::cloud_table_client client = get_table_client(); + client.set_authentication_scheme(azure::storage::authentication_scheme::shared_key_lite); + + utility::string_t prefix = object_name_prefix; + azure::storage::table_request_options options; + azure::storage::operation_context context; + std::vector results = list_all_tables(client, prefix, options, context); + CHECK(results.size() >= TABLE_COUNT); + + for (int i = 0; i < TABLE_COUNT; ++i) + { + tables[i].delete_table(); + } + } } diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp index 970f9c47..0abd0095 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp @@ -29,14 +29,11 @@ std::vector execute_table_query( azure::storage::operation_context context) { std::vector results; - - azure::storage::continuation_token token; - do + azure::storage::table_query_iterator end_of_result; + for (azure::storage::table_query_iterator iter = table.execute_query(query, options, context); iter != end_of_result; ++iter) { - azure::storage::table_query_segment result_segment = table.execute_query_segmented(query, token, options, context); - results.insert(results.end(), result_segment.results().begin(), result_segment.results().end()); - token = result_segment.continuation_token(); - } while (!token.empty()); + results.push_back(*iter); + } return results; } @@ -3591,7 +3588,7 @@ SUITE(Table) std::vector results = execute_table_query(table, query, options, context); CHECK(results.size() > 0); - CHECK((int)results.size() > take_count); + CHECK_EQUAL(take_count, (int)results.size()); for (std::vector::const_iterator entity_iterator = results.cbegin(); entity_iterator != results.cend(); ++entity_iterator) { @@ -3878,7 +3875,7 @@ SUITE(Table) std::vector results = execute_table_query(table, query, options, context); CHECK(results.size() > 0); - CHECK((int)results.size() > take_count); + CHECK_EQUAL(take_count, (int)results.size()); for (std::vector::const_iterator entity_iterator = results.cbegin(); entity_iterator != results.cend(); ++entity_iterator) { diff --git a/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp b/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp new file mode 100644 index 00000000..360c13fe --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/tests/result_iterator_test.cpp @@ -0,0 +1,222 @@ +// ----------------------------------------------------------------------------------------- +// +// Copyright 2013 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------------------- + +#include "stdafx.h" +#include "check_macros.h" +#include "test_base.h" +#include "wascore/util.h" + +typedef std::function(const azure::storage::continuation_token &, size_t)> result_generator_type; + +class test_result_provider +{ +public: + test_result_provider(size_t total_results, size_t max_results_per_segment, bool return_full_segment) + : m_returned_results(0), m_total_results(total_results), m_max_results_per_segment(max_results_per_segment), m_return_full_segment(return_full_segment) + { + } + + azure::storage::result_segment get_next_segment(const azure::storage::continuation_token &token, size_t maximum_results) + { + if (token.next_marker() != m_expected_token.next_marker()) + { + throw std::runtime_error("unexpected continuation token"); + } + + if (m_returned_results >= m_total_results) + { + // all results have been returned + return azure::storage::result_segment(); + } + + if (maximum_results == 0 || maximum_results > m_max_results_per_segment) + { + // each segment return up to "m_max_results_per_segment" results + maximum_results = m_max_results_per_segment; + } + + size_t res_segment_size = (size_t)std::min(m_total_results - m_returned_results, maximum_results); + if (!m_return_full_segment) + { + // return less results + res_segment_size = std::rand() % (res_segment_size + 1); + } + + std::vector res_vec; + res_vec.reserve(res_segment_size); + for (size_t i = 1; i <= res_segment_size; ++i) { + res_vec.push_back((int)(m_returned_results + i)); + } + + m_returned_results += res_segment_size; + + if (m_returned_results == m_total_results) + { + m_expected_token = azure::storage::continuation_token(); + } + else + { + m_expected_token = azure::storage::continuation_token(azure::storage::core::convert_to_string(m_returned_results)); + } + + return azure::storage::result_segment(res_vec, m_expected_token); + } + +private: + size_t m_returned_results; + size_t m_total_results; + size_t m_max_results_per_segment; + bool m_return_full_segment; + azure::storage::continuation_token m_expected_token; +}; + +result_generator_type get_result_generator(test_result_provider& result_provider) +{ + return [&result_provider](const azure::storage::continuation_token &token, size_t max_results_per_segment) -> azure::storage::result_segment + { + return result_provider.get_next_segment(token, max_results_per_segment); + }; +} + +void result_iterator_check_result_number(result_generator_type generator, size_t max_results, size_t max_results_per_segment, size_t num_of_results) +{ + azure::storage::result_iterator end_of_results; + azure::storage::result_iterator iter(generator, max_results, max_results_per_segment); + int count = 0; + while (iter != end_of_results) + { + count++; + CHECK(*iter == count); + + iter++; + } + + CHECK_EQUAL(num_of_results, (size_t)count); +} + +SUITE(Core) +{ + TEST_FIXTURE(test_base, result_iterator_default_constructor) + { + azure::storage::result_iterator iter; + CHECK_THROW(*iter, std::runtime_error); + + CHECK(iter++ == iter); + CHECK(++iter == iter); + } + + TEST_FIXTURE(test_base, result_iterator_get_results) + { + size_t test_data[][6] = { + /*{total_results, segment_size, return_full_segment, max_results, max_results_per_segment, num_of_results_returned}*/ + { 0, 1000, 1, 0, 0, 0 }, // empty result + { 1, 1000, 1, 0, 0, 1 }, // one result + { 99, 1000, 1, 0, 0, 99 }, // num_of_results = max_results_per_segment - 1 + { 100, 1000, 1, 0, 0, 100 }, // num_of_results = max_results_per_segment + { 101, 1000, 1, 0, 0, 101 }, // num_of_results = max_results_per_segment + 1 + { 200, 1000, 1, 0, 0, 200 }, // num_of_results = max_results_per_segment * 2 + { 3199, 1000, 1, 0, 0, 3199 }, // num_of_results = max_results_per_segment * 32 - 1 + { 3200, 1000, 1, 0, 0, 3200 }, // num_of_results = max_results_per_segment * 32 + { 3201, 1000, 1, 0, 0, 3201 }, // num_of_results = max_results_per_segment * 32 + 1 + { 100, 1000, 1, 1, 0, 1 }, // return partial results: max_results = 1 + { 100, 1000, 1, 50, 0, 50 }, // return partial results: max_results = 50 + { 100, 1000, 1, 99, 0, 99 }, // return partial results: max_results = 99 + { 100, 1000, 1, 100, 0, 100 }, // return all results: max_results = 100 + { 100, 1000, 1, 1, 1, 1 }, // max_results_per_segment = 1 + { 100, 1000, 1, 50, 1, 50 }, // max_results_per_segment = 1 + { 100, 1000, 1, 50, 2, 50 }, // max_results_per_segment = 2 + { 100, 1000, 1, 99, 50, 99 }, // max_results_per_segment = 50 + { 100, 1000, 1, 90, 200, 90 }, // max_results_per_segment = 200 + { 100, 1000, 1, 90, 1000, 90 }, // max_results_per_segment = 1000 + { 100, 1000, 1, 90, 2000, 90 }, // max_results_per_segment = 2000 + { 250, 1000, 1, 251, 10, 250 }, // max_results > total_results + { 250, 1000, 1, 500, 50, 250 }, // max_results > total_results + { 250, 1000, 1, 1000, 1000, 250 }, // max_results > total_results + { 500, 100, 0, 20, 50, 20 }, // return_full_segment = false + { 500, 100, 0, 400, 100, 400 }, // return_full_segment = false + { 500, 100, 0, 1000, 100, 500 }, // return_full_segment = false + }; + + for (auto& data : test_data) + { + test_result_provider provider(data[0], data[1], data[2] != 0); + auto generator = get_result_generator(provider); + + result_iterator_check_result_number(generator, data[3], data[4], data[5]); + } + } + + TEST_FIXTURE(test_base, result_iterator_fail_to_fetch_first_segment) + { + auto generator = [](const azure::storage::continuation_token &, size_t ) -> azure::storage::result_segment + { + throw std::runtime_error("result_iterator first segment error"); + }; + + CHECK_THROW(azure::storage::result_iterator(generator, 0, 0), std::runtime_error); + } + + TEST_FIXTURE(test_base, result_iterator_fail_to_fetch_next_segment) + { + test_result_provider provider(1000, 200, true); + bool throw_exception_in_result_generator = false; + auto generator = [&provider, &throw_exception_in_result_generator](const azure::storage::continuation_token &token, size_t max_results_per_segment) -> azure::storage::result_segment + { + if (throw_exception_in_result_generator) + { + throw std::runtime_error("result_iterator next segment error"); + } + else + { + return provider.get_next_segment(token, max_results_per_segment); + } + }; + + azure::storage::result_iterator end_of_results; + azure::storage::result_iterator iter(generator, 0, 0); + + int count = 0; + try + { + for (; iter != end_of_results; ++iter) + { + count++; + CHECK(*iter == (int)count); + + if (count == 600) + { + throw_exception_in_result_generator = true; + } + } + } + catch (std::runtime_error&) + { + } + + CHECK_EQUAL(600, count); + + throw_exception_in_result_generator = false; + + // retry to continue. the iterator shall be able to read out remaining results upon successful retry + ++iter; + for (; iter != end_of_results; ++iter) + { + count++; + CHECK(*iter == (int)count); + } + } +} diff --git a/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp b/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp index c731d442..9e145dc0 100644 --- a/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp @@ -110,6 +110,22 @@ static azure::storage::retry_info create_fake_retry_info(azure::storage::storage SUITE(Core) { + TEST_FIXTURE(test_base, retry_policy_default_constructor) + { + azure::storage::retry_policy null_policy; + CHECK(!null_policy.is_valid()); + + azure::storage::retry_context dummy_context(0, azure::storage::request_result(), azure::storage::storage_location::primary, azure::storage::location_mode::primary_only); + azure::storage::retry_info info = null_policy.evaluate(dummy_context, azure::storage::operation_context()); + CHECK(!info.should_retry()); + CHECK(info.target_location() == azure::storage::storage_location::unspecified); + CHECK(info.updated_location_mode() == azure::storage::location_mode::unspecified); + CHECK(info.retry_interval() == std::chrono::milliseconds()); + + azure::storage::retry_policy null_policy2 = null_policy.clone(); + CHECK(!null_policy2.is_valid()); + } + TEST_FIXTURE(test_base, retry_info) { { diff --git a/Microsoft.WindowsAzure.Storage/tests/unicode_test.cpp b/Microsoft.WindowsAzure.Storage/tests/unicode_test.cpp new file mode 100644 index 00000000..b8d3ded1 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/tests/unicode_test.cpp @@ -0,0 +1,73 @@ +// ----------------------------------------------------------------------------------------- +// +// Copyright 2013 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// ----------------------------------------------------------------------------------------- + +#include "stdafx.h" +#include "check_macros.h" +#include "blob_test_base.h" +#include "queue_test_base.h" +#include "table_test_base.h" + +const std::string error_invalid_characters_in_resource_name("The specifed resource name contains invalid characters."); +const std::string error_bad_request("Bad Request"); + +SUITE(Core) +{ + TEST_FIXTURE(container_test_base, container_name_unicode) + { + auto container = m_client.get_container_reference(U("容器1")); + CHECK_STORAGE_EXCEPTION(container.exists(), error_invalid_characters_in_resource_name); + CHECK_STORAGE_EXCEPTION(container.create_if_not_exists(), error_invalid_characters_in_resource_name); + } + + TEST_FIXTURE(blob_test_base, directory_name_unicode) + { + utility::string_t dir_name(U("目录1")); + utility::string_t blob_name(U("block_blob")); + auto dir = m_container.get_directory_reference(dir_name); + auto blob = dir.get_block_blob_reference(blob_name); + blob.upload_text(U("test")); + CHECK(blob.exists()); + CHECK(blob.name() == dir_name + U("/") + blob_name); + } + + TEST_FIXTURE(blob_test_base, blob_name_unicode) + { + utility::string_t blob_name(U("文件1")); + auto blob = m_container.get_block_blob_reference(blob_name); + blob.upload_text(U("test2")); + CHECK(blob.exists()); + CHECK(blob.name() == blob_name); + } + + TEST_FIXTURE(queue_service_test_base, queue_name_unicode) + { + utility::string_t queue_name(U("队列1")); + azure::storage::cloud_queue_client client = get_queue_client(); + azure::storage::cloud_queue queue = client.get_queue_reference(queue_name); + CHECK_STORAGE_EXCEPTION(queue.exists(), error_invalid_characters_in_resource_name); + CHECK_STORAGE_EXCEPTION(queue.create(), error_invalid_characters_in_resource_name); + } + + TEST_FIXTURE(table_service_test_base, table_name_unicode) + { + utility::string_t table_name(U("表格1")); + azure::storage::cloud_table_client client = get_table_client(); + azure::storage::cloud_table table = client.get_table_reference(table_name); + CHECK(false == table.exists()); + CHECK_STORAGE_EXCEPTION(table.create(), error_bad_request); + } +} diff --git a/Microsoft.WindowsAzure.Storage/version.rc b/Microsoft.WindowsAzure.Storage/version.rc index b40491e59de6b75e82e9eb09dc8162b0ac7db84a..899276b8e4c29297dc4b772aec89afa993344741 100644 GIT binary patch delta 57 zcmX@2d_;Le7YC~$gARki + +