From adabd7737173ffa2be7536e9c138340d5e8c7f4b Mon Sep 17 00:00:00 2001 From: asorrin-msft Date: Wed, 3 Dec 2014 13:31:27 -0800 Subject: [PATCH] Azure Storage Client Library for C++ v0.4.0 --- BreakingChanges.txt | 3 + Changelog.txt | 16 ++ Microsoft.WindowsAzure.Storage.autopkg | 10 +- Microsoft.WindowsAzure.Storage/CMakeLists.txt | 102 +++++++ Microsoft.WindowsAzure.Storage/Makefile | 28 ++ ...icrosoft.WindowsAzure.Storage.v120.vcxproj | 25 +- ....WindowsAzure.Storage.v120.vcxproj.filters | 30 +- .../Microsoft.WindowsAzure.Storage.vcxproj | 25 +- ...osoft.WindowsAzure.Storage.vcxproj.filters | 30 +- .../cmake/Modules/FindCasablanca.cmake | 39 +++ .../cmake/Modules/FindGlib.cmake | 40 +++ .../cmake/Modules/FindGlibmm.cmake | 39 +++ .../cmake/Modules/FindLibXML++.cmake | 39 +++ .../cmake/Modules/FindLibXML2.cmake | 44 +++ .../cmake/Modules/FindSigC++.cmake | 35 +++ .../cmake/Modules/FindUUID.cmake | 113 ++++++++ .../cmake/Modules/LibFindMacros.cmake | 266 +++++++++++++++++ .../includes/targetver.h | 2 + .../includes/was/blob.h | 44 ++- .../includes/was/common.h | 119 +++++++- .../includes/was/core.h | 91 +++--- .../includes/was/queue.h | 2 +- .../includes/was/retry_policies.h | 2 +- .../includes/was/service_client.h | 5 +- .../includes/was/table.h | 8 +- .../includes/wascore/basic_types.h | 5 +- .../includes/wascore/blobstreams.h | 16 +- .../includes/wascore/constants.h | 11 +- .../includes/wascore/executor.h | 150 ++++++---- .../includes/wascore/hashing.h | 268 +++++++++++++++++ .../includes/wascore/logging.h | 3 + .../includes/wascore/protocol.h | 5 +- .../includes/wascore/protocol_xml.h | 70 +++-- .../includes/wascore/streambuf.h | 269 +++--------------- .../includes/wascore/streams.h | 66 +---- .../includes/wascore/xmlhelpers.h | 1 + .../packages.config | 6 +- .../BlobsGettingStarted/Application.cpp | 9 +- .../BlobsGettingStarted/CMakeLists.txt | 57 ++++ ...e.Storage.BlobsGettingStarted.v120.vcxproj | 9 +- ...sAzure.Storage.BlobsGettingStarted.vcxproj | 9 +- .../BlobsGettingStarted/packages.config | 6 +- .../samples/BlobsGettingStarted/stdafx.h | 2 - .../samples/CMakeLists.txt | 110 +++++++ .../samples/JsonPayloadFormat/Application.cpp | 11 +- .../samples/JsonPayloadFormat/CMakeLists.txt | 57 ++++ ...ure.Storage.JsonPayloadFormat.v120.vcxproj | 9 +- ...owsAzure.Storage.JsonPayloadFormat.vcxproj | 9 +- .../samples/JsonPayloadFormat/packages.config | 6 +- .../samples/JsonPayloadFormat/stdafx.h | 2 - .../QueuesGettingStarted/Application.cpp | 11 +- .../QueuesGettingStarted/CMakeLists.txt | 57 ++++ ....Storage.QueuesGettingStarted.v120.vcxproj | 9 +- ...Azure.Storage.QueuesGettingStarted.vcxproj | 9 +- .../QueuesGettingStarted/packages.config | 6 +- .../samples/QueuesGettingStarted/stdafx.h | 2 - .../samples/SamplesCommon/CMakeLists.txt | 56 ++++ .../TablesGettingStarted/Application.cpp | 13 +- .../TablesGettingStarted/CMakeLists.txt | 57 ++++ ....Storage.TablesGettingStarted.v120.vcxproj | 9 +- ...Azure.Storage.TablesGettingStarted.vcxproj | 9 +- .../TablesGettingStarted/packages.config | 6 +- .../samples/TablesGettingStarted/stdafx.h | 2 - .../src/CMakeLists.txt | 135 +++++++++ Microsoft.WindowsAzure.Storage/src/Makefile | 146 ++++++++++ .../src/authentication.cpp | 10 +- .../src/basic_types.cpp | 22 +- .../src/cloud_blob.cpp | 193 +++++++++---- .../src/cloud_blob_client.cpp | 8 +- .../src/cloud_blob_container.cpp | 60 ++-- .../src/cloud_blob_istreambuf.cpp | 31 +- .../src/cloud_blob_ostreambuf.cpp | 33 ++- .../src/cloud_block_blob.cpp | 29 +- .../src/cloud_client.cpp | 10 +- .../src/cloud_common.cpp | 30 ++ .../src/cloud_page_blob.cpp | 27 +- .../src/cloud_queue.cpp | 63 ++-- .../src/cloud_queue_client.cpp | 11 +- .../src/cloud_table.cpp | 38 +-- .../src/cloud_table_client.cpp | 2 +- .../src/hashing.cpp | 146 ++++++++++ .../src/logging.cpp | 164 +++++++++++ .../src/protocol_xml.cpp | 92 +++--- .../src/request_factory.cpp | 1 + .../src/request_result.cpp | 7 +- .../src/response_parsers.cpp | 21 +- .../src/retry_policies.cpp | 1 + .../src/shared_access_signature.cpp | 17 +- .../src/table_response_parsers.cpp | 4 +- Microsoft.WindowsAzure.Storage/src/util.cpp | 85 +++++- .../src/xmlhelpers.cpp | 2 +- .../tests/CMakeLists.txt | 97 +++++++ ...indowsAzure.Storage.UnitTests.v120.vcxproj | 11 +- ...ure.Storage.UnitTests.v120.vcxproj.filters | 2 +- ...oft.WindowsAzure.Storage.UnitTests.vcxproj | 11 +- ...owsAzure.Storage.UnitTests.vcxproj.filters | 2 +- .../tests/README.md | 2 +- .../tests/blob_streams_test.cpp | 8 +- .../tests/blob_test_base.cpp | 10 +- .../tests/cloud_blob_client_test.cpp | 20 +- .../tests/cloud_blob_test.cpp | 4 +- .../tests/cloud_block_blob_test.cpp | 65 ++++- .../tests/cloud_page_blob_test.cpp | 2 +- .../tests/cloud_queue_client_test.cpp | 9 +- .../tests/cloud_queue_test.cpp | 7 +- .../tests/cloud_table_client_test.cpp | 9 +- .../tests/cloud_table_test.cpp | 159 ++++++----- Microsoft.WindowsAzure.Storage/tests/main.cpp | 25 ++ .../tests/packages.config | 6 +- .../tests/read_from_secondary_test.cpp | 2 +- .../tests/retry_policy_test.cpp | 28 ++ .../tests/service_properties_test.cpp | 41 ++- .../tests/targetver.h | 2 + .../tests/test_base.cpp | 2 +- .../tests/test_helper.cpp | 4 +- Microsoft.WindowsAzure.Storage/version.rc | Bin 4548 -> 4548 bytes README.md | 8 +- build.root | 1 + 118 files changed, 3520 insertions(+), 974 deletions(-) create mode 100644 Microsoft.WindowsAzure.Storage/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/Makefile create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindCasablanca.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlib.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlibmm.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML++.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML2.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindSigC++.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/FindUUID.cmake create mode 100644 Microsoft.WindowsAzure.Storage/cmake/Modules/LibFindMacros.cmake create mode 100644 Microsoft.WindowsAzure.Storage/includes/wascore/hashing.h create mode 100644 Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/samples/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/samples/SamplesCommon/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/src/CMakeLists.txt create mode 100644 Microsoft.WindowsAzure.Storage/src/Makefile create mode 100644 Microsoft.WindowsAzure.Storage/src/cloud_common.cpp create mode 100644 Microsoft.WindowsAzure.Storage/src/hashing.cpp create mode 100644 Microsoft.WindowsAzure.Storage/src/logging.cpp create mode 100644 Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt create mode 100644 build.root diff --git a/BreakingChanges.txt b/BreakingChanges.txt index df3eacf8..deea1886 100644 --- a/BreakingChanges.txt +++ b/BreakingChanges.txt @@ -1,6 +1,9 @@ Azure Storage Client Library for C++ History of Breaking Changes +Breaking Changes in v0.4: +- Upgraded Casablanca dependency to 2.3.0 + Breaking changes in v0.3: - Changed namespace to azure::storage. - The SAS token returned by the get_shared_access_signature functions does not include a question mark (?) prefix. diff --git a/Changelog.txt b/Changelog.txt index 1eff958e..466082e0 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,6 +1,22 @@ Azure Storage Client Library for C++ History of Changes +Changes in v0.4: +- Now supports building on Linux +- Added http_buffer_size request option to control the internal buffer size used in the HTTP layer when downloading data. The default size is 64KB. +- Blob downloads that are interrupted resume automatically from where the download left off when being retried. +- Performance improvement when uploading and downloading blobs. +- Added const version of the operation_context::user_headers() function. +- Fixed incorrect initialization of some members in the cloud_blob_container_properties and retry_info classes. +- Added a default of 24 days for a maximum execution time for an operation +- Changed the exception type if you upload a blob from a seekable stream but the stream is too short for the desired blob length. + - Used to throw azure::storage::storage_exception in some cases, now throws std::invalid_argument always. + - Now checks for this case explicitly before the upload is started. + - Non-seekable streams still throw std::invalid_argument as before. +- Fixed several bugs, including incorrect uses of std::move and compile-time differences between Visual Studio and g++. +- Added client request ID into log lines. +- Upgraded Casablanca dependency to 2.3.0 + Changes in v0.3: - Changed namespace to azure::storage. - Added support for secondary location access in Azure Storage Emulator. diff --git a/Microsoft.WindowsAzure.Storage.autopkg b/Microsoft.WindowsAzure.Storage.autopkg index e4f4cf40..aba167d9 100644 --- a/Microsoft.WindowsAzure.Storage.autopkg +++ b/Microsoft.WindowsAzure.Storage.autopkg @@ -1,23 +1,23 @@ nuget { nuspec { id = wastorage; - version: 0.3.0-preview; + version: 0.4.0-preview; title: Microsoft Azure Storage Client Library for C++; authors: {Microsoft Corporation}; owners: {Microsoft Corporation}; licenseUrl: "http://go.microsoft.com/fwlink/?LinkId=235170"; projectUrl: "http://go.microsoft.com/fwlink/?LinkId=235168"; iconUrl: "http://go.microsoft.com/fwlink/?LinkID=288890"; - summary: "A client library for working with Azure storage services including blobs, tables, and queues."; - description: @"This client library enables working with the 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. - Azure Storage team's blog - http://blogs.msdn.com/b/windowsazurestorage/"; + 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"; tags: { Microsoft, Azure, Storage, Table, Blob, Queue, Scalable, windowsazureofficial }; } dependencies { packages: { - cpprestsdk/2.0.1 + cpprestsdk/2.3.0 }; } diff --git a/Microsoft.WindowsAzure.Storage/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/CMakeLists.txt new file mode 100644 index 00000000..00e03c93 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/CMakeLists.txt @@ -0,0 +1,102 @@ +set(CMAKE_LEGACY_CYGWIN_WIN32 0) +cmake_minimum_required(VERSION 2.6) +project(azurestorage) + +enable_testing() + +set(WARNINGS) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") + +# Platform (not compiler) specific settings +if(IOS) + set(IOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../Build_iOS") + set(Boost_FRAMEWORK "-F ${IOS_SOURCE_DIR} -framework boost") + set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers") + + set(OPENSSL_FOUND 1) + set(OPENSSL_INCLUDE_DIR "${IOS_SOURCE_DIR}/openssl/include") + set(OPENSSL_LIBRARIES + "${IOS_SOURCE_DIR}/openssl/lib/libcrypto.a" + "${IOS_SOURCE_DIR}/openssl/lib/libssl.a" + ) + + set(CASABLANCA_INCLUDE_DIRS "${IOS_SOURCE_DIR}/casablanca/include") + set(CASABLANCA_LIBRARIES "${IOS_SOURCE_DIR}/casablanca/lib/libcasablanca.a") + + # The cxx_flags must be set here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. + set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") + + set(BUILD_SHARED_LIBS OFF) +elseif(UNIX) # This includes OSX + find_package(Boost REQUIRED COMPONENTS log log_setup random system thread locale regex filesystem) + find_package(Threads REQUIRED) + find_package(OpenSSL REQUIRED) + find_package(LibXML++ REQUIRED) + find_package(UUID REQUIRED) + find_package(Casablanca REQUIRED) + + set(UNITTEST_LIBRARY "${CMAKE_SOURCE_DIR}/tests/UnitTest++/libUnitTest++.a") + + option(BUILD_SHARED_LIBS "Build shared Libraries." ON) +elseif(WIN32) + option(BUILD_SHARED_LIBS "Build shared Libraries." ON) + + add_definitions(-DUNICODE) + + if(NOT BUILD_SHARED_LIBS) + # This causes cmake to not link the test libraries separately, but instead hold onto their object files. + set(TEST_LIBRARY_TARGET_TYPE OBJECT) + endif() + + set(LIB lib) +else() + message("-- Unsupported Build Platform.") +endif() + +# Compiler (not platform) specific settings +if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR IOS) + message("-- Setting clang options") + + set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") + set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder") + set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") + set(STRICT_CXX_FLAGS ${WARNINGS} "-Werror -pedantic") +elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + message("-- Setting gcc options") + + set(WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code") + set(LINUX_SUPPRESSIONS "-Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-unused-function -Wno-char-subscripts -Wno-switch -Wno-unused-but-set-parameter -Wno-unused-value -Wno-unused-local-typedefs -Wno-unused-parameter") + + set(WARNINGS "${WARNINGS} ${LINUX_SUPPRESSIONS}") + set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") + set(STRICT_CXX_FLAGS ${WARNINGS} "-Werror -pedantic") + add_definitions(-DBOOST_LOG_DYN_LINK) +else() + message("-- Unknown compiler, success is doubtful.") +endif() + +# Reconfigure final output directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) + +set(AZURESTORAGE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/includes) +set(AZURESTORAGE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/includes ${CASABLANCA_INCLUDE_DIRS} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}) + +set(AZURESTORAGE_LIBRARY azurestorage) +set(AZURESTORAGE_LIBRARY_TEST azurestoragetest) +set(AZURESTORAGE_LIBRARIES ${AZURESTORAGE_LIBRARY} ${CASABLANCA_LIBRARIES} ${Boost_LIBRARIES} ${Boost_FRAMEWORK} ${OPENSSL_LIBRARIES} ${LibXML++_LIBRARIES} ${UUID_LIBRARIES}) + +include_directories(${AZURESTORAGE_INCLUDE_DIRS}) + +add_subdirectory(src) +add_subdirectory(tests) diff --git a/Microsoft.WindowsAzure.Storage/Makefile b/Microsoft.WindowsAzure.Storage/Makefile new file mode 100644 index 00000000..da6a48a5 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/Makefile @@ -0,0 +1,28 @@ +MODE = $(shell getconf LONG_BIT) + +debug: + mkdir -vp build.debug$(MODE) + cd build.debug$(MODE) && CXX=g++-4.8 cmake .. -DCMAKE_BUILD_TYPE=Debug && cmake --build . + +release: + mkdir -vp build.release$(MODE) + cd build.release$(MODE) && CXX=g++-4.8 cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build . + +clean: + @[ -e src ] # sanity check directory + @find . -iname *.so -exec rm '{}' \; + @find . -iname *.o -exec rm '{}' \; + @find . -iname *.d -exec rm '{}' \; + @find ../Binaries -iname *.so -exec rm '{}' \; + @find ../Binaries -iname *.txt -exec rm '{}' \; + @find ../Binaries -iname *.d -exec rm '{}' \; + @find ../Binaries -iname SearchFile -exec rm '{}' \; + @find ../Binaries -iname BingRequest -exec rm '{}' \; + @find ../Binaries -iname syncdir -exec rm '{}' \; + @find ../Binaries -iname test_runner -exec rm '{}' \; + @rm -rf build.debug* build.release* + + +all: debug release + +.PHONY: all clean release debug diff --git a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj index 764463ce..cccc279b 100644 --- a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -103,7 +104,7 @@ WASTORAGE_DLL;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true true - /we4100 /Zm129 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -121,7 +122,7 @@ WASTORAGE_DLL;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true true - /we4100 /Zm129 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -142,7 +143,7 @@ true false true - /we4100 /Zm122 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -165,7 +166,7 @@ true false true - /we4100 /Zm122 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -193,7 +194,7 @@ - + @@ -208,6 +209,7 @@ + @@ -229,8 +231,8 @@ - - + + @@ -254,7 +256,6 @@ Create Create - @@ -265,7 +266,11 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj.filters b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj.filters index 3cb439f5..aae6c14d 100644 --- a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj.filters +++ b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.v120.vcxproj.filters @@ -33,9 +33,6 @@ Header Files - - Header Files - Header Files @@ -69,9 +66,6 @@ Header Files - - Source Files - Header Files @@ -102,6 +96,9 @@ Header Files + + Header Files + @@ -164,9 +161,6 @@ Source Files - - Source Files - Source Files @@ -197,9 +191,6 @@ Source Files - - Source Files - Source Files @@ -215,9 +206,6 @@ Source Files - - Source Files - Source Files @@ -230,6 +218,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + diff --git a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj index f51c2fc9..1bb32482 100644 --- a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj +++ b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -103,7 +104,7 @@ WASTORAGE_DLL;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true true - /we4100 /Zm129 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -121,7 +122,7 @@ WASTORAGE_DLL;WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true true - /we4100 /Zm129 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -142,7 +143,7 @@ true false true - /we4100 /Zm122 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -165,7 +166,7 @@ true false true - /we4100 /Zm122 %(AdditionalOptions) /bigobj + /we4100 /Zm150 %(AdditionalOptions) /bigobj true includes @@ -193,7 +194,7 @@ - + @@ -221,6 +222,7 @@ + @@ -229,8 +231,8 @@ - - + + @@ -254,7 +256,6 @@ Create Create - @@ -265,7 +266,11 @@ + + + + + - \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj.filters b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj.filters index 3cb439f5..aae6c14d 100644 --- a/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj.filters +++ b/Microsoft.WindowsAzure.Storage/Microsoft.WindowsAzure.Storage.vcxproj.filters @@ -33,9 +33,6 @@ Header Files - - Header Files - Header Files @@ -69,9 +66,6 @@ Header Files - - Source Files - Header Files @@ -102,6 +96,9 @@ Header Files + + Header Files + @@ -164,9 +161,6 @@ Source Files - - Source Files - Source Files @@ -197,9 +191,6 @@ Source Files - - Source Files - Source Files @@ -215,9 +206,6 @@ Source Files - - Source Files - Source Files @@ -230,6 +218,18 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindCasablanca.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindCasablanca.cmake new file mode 100644 index 00000000..f8090d74 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindCasablanca.cmake @@ -0,0 +1,39 @@ +# FindCasablanca package +# +# Tries to find the Casablanca (C++ REST SDK) library +# + +find_package(PkgConfig) + +include(LibFindMacros) + +# Include dir +find_path(CASABLANCA_INCLUDE_DIR + NAMES cpprest/http_client.h + PATHS + ${CASABLANCA_PKGCONF_INCLUDE_DIRS} + ${CASABLANCA_DIR} + $ENV{CASABLANCA_DIR} + /usr/local/include + /usr/include + PATH_SUFFIXES Release/include include +) + +# Library +find_library(CASABLANCA_LIBRARY + NAMES libcpprest.so + PATHS + ${CASABLANCA_PKGCONF_LIBRARY_DIRS} + ${CASABLANCA_DIR} + ${CASABLANCA_DIR}/lib + $ENV{CASABLANCA_DIR}/lib + $ENV{CASABLANCA_DIR} + /usr/local/lib + /usr/lib + PATH_SUFFIXES Release/build.release/Binaries/ build.release/Binaries/ +) + +set(CASABLANCA_PROCESS_LIBS CASABLANCA_LIBRARY) +set(CASABLANCA_PROCESS_INCLUDES CASABLANCA_INCLUDE_DIR) +libfind_process(CASABLANCA) + diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlib.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlib.cmake new file mode 100644 index 00000000..708cdc72 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlib.cmake @@ -0,0 +1,40 @@ +# - Try to find Glib-2.0 (with gobject) +# Once done, this will define +# +# Glib_FOUND - system has Glib +# Glib_INCLUDE_DIRS - the Glib include directories +# Glib_LIBRARIES - link these to use Glib + +include(LibFindMacros) + +# Use pkg-config to get hints about paths +libfind_pkg_check_modules(Glib_PKGCONF glib-2.0) + +# Main include dir +find_path(Glib_INCLUDE_DIR + NAMES glib.h + PATHS ${Glib_PKGCONF_INCLUDE_DIRS} + PATH_SUFFIXES glib-2.0 +) + +# Glib-related libraries also use a separate config header, which is in lib dir +find_path(GlibConfig_INCLUDE_DIR + NAMES glibconfig.h + PATHS ${Glib_PKGCONF_INCLUDE_DIRS} /usr + PATH_SUFFIXES lib/glib-2.0/include +) + +# Finally the library itself +find_library(Glib_LIBRARY + NAMES glib-2.0 + PATHS ${Glib_PKGCONF_LIBRARY_DIRS} +) + +# Set the include dir variables and the libraries and let libfind_process do the rest. +# NOTE: Singular variables for this library, plural for libraries this this lib depends on. +set(Glib_PROCESS_INCLUDES Glib_INCLUDE_DIR GlibConfig_INCLUDE_DIR) +set(Glib_PROCESS_LIBS Glib_LIBRARY) +libfind_process(Glib) + + + diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlibmm.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlibmm.cmake new file mode 100644 index 00000000..375b8cdd --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindGlibmm.cmake @@ -0,0 +1,39 @@ +# - Try to find Glibmm-2.4 +# Once done, this will define +# +# Glibmm_FOUND - system has Glibmm +# Glibmm_INCLUDE_DIRS - the Glibmm include directories +# Glibmm_LIBRARIES - link these to use Glibmm + +include(LibFindMacros) + +# Dependencies +libfind_package(Glibmm Glib) +libfind_package(Glibmm SigC++) + +# Use pkg-config to get hints about paths +libfind_pkg_check_modules(Glibmm_PKGCONF glibmm-2.4) + +# Main include dir +find_path(Glibmm_INCLUDE_DIR + NAMES glibmm/main.h + PATHS ${Glibmm_PKGCONF_INCLUDE_DIRS} + PATH_SUFFIXES glibmm-2.4 +) + +# Glib-related libraries also use a separate config header, which is in lib dir +find_path(GlibmmConfig_INCLUDE_DIR + NAMES glibmmconfig.h + PATHS ${Glibmm_PKGCONF_INCLUDE_DIRS} /usr + PATH_SUFFIXES lib/glibmm-2.4/include +) + +libfind_library(Glibmm glibmm 2.4) + +# Set the include dir variables and the libraries and let libfind_process do the rest. +# NOTE: Singular variables for this library, plural for libraries this this lib depends on. +set(Glibmm_PROCESS_INCLUDES Glibmm_INCLUDE_DIR GlibmmConfig_INCLUDE_DIR Glib_INCLUDE_DIRS SigC++_INCLUDE_DIRS) +set(Glibmm_PROCESS_LIBS Glibmm_LIBRARY Glib_LIBRARIES SigC++_LIBRARIES) +libfind_process(Glibmm) + + diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML++.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML++.cmake new file mode 100644 index 00000000..d50fb442 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML++.cmake @@ -0,0 +1,39 @@ +# find libxml++ +# +# exports: +# +# LibXML++_FOUND +# LibXML++_INCLUDE_DIRS +# LibXML++_LIBRARIES +# + +include(FindPkgConfig) +include(FindPackageHandleStandardArgs) + +# Use pkg-config to get hints about paths +pkg_check_modules(LibXML++_PKGCONF REQUIRED libxml++-2.6) + +# Include dir +find_path(LibXML++_INCLUDE_DIR + NAMES libxml++/libxml++.h + PATHS ${LibXML++_PKGCONF_INCLUDE_DIRS} +) + +# Finally the library itself +find_library(LibXML++_LIBRARY + NAMES xml++ xml++-2.6 + PATHS ${LibXML++_PKGCONF_LIBRARY_DIRS} +) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibXML++ DEFAULT_MSG LibXML++_LIBRARY LibXML++_INCLUDE_DIR) + + +if(LibXML++_PKGCONF_FOUND) + set(LibXML++_LIBRARIES ${LibXML++_LIBRARY} ${LibXML++_PKGCONF_LIBRARIES}) + set(LibXML++_INCLUDE_DIRS ${LibXML++_INCLUDE_DIR} ${LibXML++_PKGCONF_INCLUDE_DIRS}) + set(LibXML++_FOUND yes) +else() + set(LibXML++_LIBRARIES) + set(LibXML++_INCLUDE_DIRS) + set(LibXML++_FOUND no) +endif() diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML2.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML2.cmake new file mode 100644 index 00000000..d1413be6 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindLibXML2.cmake @@ -0,0 +1,44 @@ +# - Try to find LibXML2 headers and libraries. +# +# Usage of this module as follows: +# +# find_package(LibXML2) +# +# Variables used by this module, they can change the default behaviour and need +# to be set before calling find_package: +# +# LibXML2_ROOT_DIR Set this variable to the root installation of +# LibXML2 if the module has problems finding +# the proper installation path. +# +# Variables defined by this module: +# +# LIBXML2_FOUND System has LibXML2 libs/headers +# LibXML2_LIBRARIES The LibXML2 libraries +# LibXML2_INCLUDE_DIR The location of LibXML2 headers + +find_path(LibXML2_ROOT_DIR + NAMES include/libxml2/libxml/tree.h +) + +find_library(LibXML2_LIBRARIES + NAMES xml2 + HINTS ${LibXML2_ROOT_DIR}/lib +) + +find_path(LibXML2_INCLUDE_DIR + NAMES libxml/tree.h + HINTS ${LibXML2_ROOT_DIR}/include/libxml2 +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(LibXML2 DEFAULT_MSG + LibXML2_LIBRARIES + LibXML2_INCLUDE_DIR +) + +mark_as_advanced( + LibXML2_ROOT_DIR + LibXML2_LIBRARIES + LibXML2_INCLUDE_DIR +) diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindSigC++.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindSigC++.cmake new file mode 100644 index 00000000..27745332 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindSigC++.cmake @@ -0,0 +1,35 @@ +# - Try to find SigC++-2.0 +# Once done, this will define +# +# SigC++_FOUND - system has SigC++ +# SigC++_INCLUDE_DIRS - the SigC++ include directories +# SigC++_LIBRARIES - link these to use SigC++ + +include(LibFindMacros) + +# Use pkg-config to get hints about paths +libfind_pkg_check_modules(SigC++_PKGCONF sigc++-2.0) + +# Main include dir +find_path(SigC++_INCLUDE_DIR + NAMES sigc++/sigc++.h + PATHS ${SigC++_PKGCONF_INCLUDE_DIRS} + PATH_SUFFIXES sigc++-2.0 +) + +# Glib-related libraries also use a separate config header, which is in lib dir +find_path(SigC++Config_INCLUDE_DIR + NAMES sigc++config.h + PATHS ${SigC++_PKGCONF_INCLUDE_DIRS} /usr + PATH_SUFFIXES lib/sigc++-2.0/include +) + +libfind_library(SigC++ sigc 2.0) + +# Set the include dir variables and the libraries and let libfind_process do the rest. +# NOTE: Singular variables for this library, plural for libraries this this lib depends on. +set(SigC++_PROCESS_INCLUDES SigC++_INCLUDE_DIR SigC++Config_INCLUDE_DIR) +set(SigC++_PROCESS_LIBS SigC++_LIBRARY) +libfind_process(SigC++) + + diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/FindUUID.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindUUID.cmake new file mode 100644 index 00000000..d64618a9 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/FindUUID.cmake @@ -0,0 +1,113 @@ +# - Try to find UUID +# Once done this will define +# +# UUID_FOUND - system has UUID +# UUID_INCLUDE_DIRS - the UUID include directory +# UUID_LIBRARIES - Link these to use UUID +# UUID_DEFINITIONS - Compiler switches required for using UUID +# +# Copyright (c) 2006 Andreas Schneider +# +# Redistribution and use is allowed according to the terms of the New +# BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. +# + + +if (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) + # in cache already + set(UUID_FOUND TRUE) +else (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) + find_path(UUID_INCLUDE_DIR + NAMES + uuid/uuid.h + PATHS + ${UUID_DIR}/include + $ENV{UUID_DIR}/include + $ENV{UUID_DIR} + ${DELTA3D_EXT_DIR}/inc + $ENV{DELTA_ROOT}/ext/inc + $ENV{DELTA_ROOT} + ~/Library/Frameworks + /Library/Frameworks + /usr/local/include + /usr/include + /usr/include/gdal + /sw/include # Fink + /opt/local/include # DarwinPorts + /opt/csw/include # Blastwave + /opt/include + [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Session\ Manager\\Environment;OSG_ROOT]/include + /usr/freeware/include + + ) + + find_library(UUID_LIBRARY + NAMES + uuid + PATHS + ${UUID_DIR}/lib + $ENV{UUID_DIR}/lib + $ENV{UUID_DIR} + ${DELTA3D_EXT_DIR}/lib + $ENV{DELTA_ROOT}/ext/lib + $ENV{DELTA_ROOT} + $ENV{OSG_ROOT}/lib + ~/Library/Frameworks + /Library/Frameworks + /usr/local/lib + /usr/lib + /sw/lib + /opt/local/lib + /opt/csw/lib + /opt/lib + /usr/freeware/lib64 + ) + + find_library(UUID_LIBRARY_DEBUG + NAMES + uuidd + PATHS + ${UUID_DIR}/lib + $ENV{UUID_DIR}/lib + $ENV{UUID_DIR} + ${DELTA3D_EXT_DIR}/lib + $ENV{DELTA_ROOT}/ext/lib + $ENV{DELTA_ROOT} + $ENV{OSG_ROOT}/lib + ~/Library/Frameworks + /Library/Frameworks + /usr/local/lib + /usr/lib + /sw/lib + /opt/local/lib + /opt/csw/lib + /opt/lib + /usr/freeware/lib64 + ) + + set(UUID_INCLUDE_DIRS + ${UUID_INCLUDE_DIR} + ) + set(UUID_LIBRARIES + ${UUID_LIBRARY} +) + + if (UUID_INCLUDE_DIRS AND UUID_LIBRARIES) + set(UUID_FOUND TRUE) + endif (UUID_INCLUDE_DIRS AND UUID_LIBRARIES) + + if (UUID_FOUND) + if (NOT UUID_FIND_QUIETLY) + message(STATUS "Found UUID: ${UUID_LIBRARIES}") + endif (NOT UUID_FIND_QUIETLY) + else (UUID_FOUND) + if (UUID_FIND_REQUIRED) + message(FATAL_ERROR "Could not find UUID") + endif (UUID_FIND_REQUIRED) + endif (UUID_FOUND) + + # show the UUID_INCLUDE_DIRS and UUID_LIBRARIES variables only in the advanced view + mark_as_advanced(UUID_INCLUDE_DIRS UUID_LIBRARIES) + +endif (UUID_LIBRARIES AND UUID_INCLUDE_DIRS) diff --git a/Microsoft.WindowsAzure.Storage/cmake/Modules/LibFindMacros.cmake b/Microsoft.WindowsAzure.Storage/cmake/Modules/LibFindMacros.cmake new file mode 100644 index 00000000..3ef5844d --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/cmake/Modules/LibFindMacros.cmake @@ -0,0 +1,266 @@ +# Version 2.2 +# Public Domain, originally written by Lasse Kärkkäinen +# Maintained at https://github.com/Tronic/cmake-modules +# Please send your improvements as pull requests on Github. + +# Find another package and make it a dependency of the current package. +# This also automatically forwards the "REQUIRED" argument. +# Usage: libfind_package( [extra args to find_package]) +macro (libfind_package PREFIX PKG) + set(${PREFIX}_args ${PKG} ${ARGN}) + if (${PREFIX}_FIND_REQUIRED) + set(${PREFIX}_args ${${PREFIX}_args} REQUIRED) + endif() + find_package(${${PREFIX}_args}) + set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG}) + unset(${PREFIX}_args) +endmacro() + +# A simple wrapper to make pkg-config searches a bit easier. +# Works the same as CMake's internal pkg_check_modules but is always quiet. +macro (libfind_pkg_check_modules) + find_package(PkgConfig QUIET) + if (PKG_CONFIG_FOUND) + pkg_check_modules(${ARGN} QUIET) + endif() +endmacro() + +# Avoid useless copy&pasta by doing what most simple libraries do anyway: +# pkg-config, find headers, find library. +# Usage: libfind_pkg_detect( FIND_PATH [other args] FIND_LIBRARY [other args]) +# E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2) +function (libfind_pkg_detect PREFIX) + # Parse arguments + set(argname pkgargs) + foreach (i ${ARGN}) + if ("${i}" STREQUAL "FIND_PATH") + set(argname pathargs) + elseif ("${i}" STREQUAL "FIND_LIBRARY") + set(argname libraryargs) + else() + set(${argname} ${${argname}} ${i}) + endif() + endforeach() + if (NOT pkgargs) + message(FATAL_ERROR "libfind_pkg_detect requires at least a pkg_config package name to be passed.") + endif() + # Find library + libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs}) + if (pathargs) + find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS}) + endif() + if (libraryargs) + find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}) + endif() +endfunction() + +# Extracts a version #define from a version.h file, output stored to _VERSION. +# Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR) +# Fourth argument "QUIET" may be used for silently testing different define names. +# This function does nothing if the version variable is already defined. +function (libfind_version_header PREFIX VERSION_H DEFINE_NAME) + # Skip processing if we already have a version or if the include dir was not found + if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR) + return() + endif() + set(quiet ${${PREFIX}_FIND_QUIETLY}) + # Process optional arguments + foreach(arg ${ARGN}) + if (arg STREQUAL "QUIET") + set(quiet TRUE) + else() + message(AUTHOR_WARNING "Unknown argument ${arg} to libfind_version_header ignored.") + endif() + endforeach() + # Read the header and parse for version number + set(filename "${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") + if (NOT EXISTS ${filename}) + if (NOT quiet) + message(AUTHOR_WARNING "Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") + endif() + return() + endif() + file(READ "${filename}" header) + string(REGEX REPLACE ".*#[ \t]*define[ \t]*${DEFINE_NAME}[ \t]*\"([^\n]*)\".*" "\\1" match "${header}") + # No regex match? + if (match STREQUAL header) + if (NOT quiet) + message(AUTHOR_WARNING "Unable to find \#define ${DEFINE_NAME} \"\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") + endif() + return() + endif() + # Export the version string + set(${PREFIX}_VERSION "${match}" PARENT_SCOPE) +endfunction() + +# Do the final processing once the paths have been detected. +# If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain +# all the variables, each of which contain one include directory. +# Ditto for ${PREFIX}_PROCESS_LIBS and library files. +# Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. +# Also handles errors in case library detection was required, etc. +function (libfind_process PREFIX) + # Skip processing if already processed during this configuration run + if (${PREFIX}_FOUND) + return() + endif() + + set(found TRUE) # Start with the assumption that the package was found + + # Did we find any files? Did we miss includes? These are for formatting better error messages. + set(some_files FALSE) + set(missing_headers FALSE) + + # Shorthands for some variables that we need often + set(quiet ${${PREFIX}_FIND_QUIETLY}) + set(required ${${PREFIX}_FIND_REQUIRED}) + set(exactver ${${PREFIX}_FIND_VERSION_EXACT}) + set(findver "${${PREFIX}_FIND_VERSION}") + set(version "${${PREFIX}_VERSION}") + + # Lists of config option names (all, includes, libs) + unset(configopts) + set(includeopts ${${PREFIX}_PROCESS_INCLUDES}) + set(libraryopts ${${PREFIX}_PROCESS_LIBS}) + + # Process deps to add to + foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES}) + if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS) + # The package seems to export option lists that we can use, woohoo! + list(APPEND includeopts ${${i}_INCLUDE_OPTS}) + list(APPEND libraryopts ${${i}_LIBRARY_OPTS}) + else() + # If plural forms don't exist or they equal singular forms + if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR + ({i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES)) + # Singular forms can be used + if (DEFINED ${i}_INCLUDE_DIR) + list(APPEND includeopts ${i}_INCLUDE_DIR) + endif() + if (DEFINED ${i}_LIBRARY) + list(APPEND libraryopts ${i}_LIBRARY) + endif() + else() + # Oh no, we don't know the option names + message(FATAL_ERROR "We couldn't determine config variable names for ${i} includes and libs. Aieeh!") + endif() + endif() + endforeach() + + if (includeopts) + list(REMOVE_DUPLICATES includeopts) + endif() + + if (libraryopts) + list(REMOVE_DUPLICATES libraryopts) + endif() + + string(REGEX REPLACE ".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))" "\\1" tmp "${includeopts} ${libraryopts}") + if (NOT tmp STREQUAL "${includeopts} ${libraryopts}") + message(AUTHOR_WARNING "Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).") + endif() + + # Include/library names separated by spaces (notice: not CMake lists) + unset(includes) + unset(libs) + + # Process all includes and set found false if any are missing + foreach (i ${includeopts}) + list(APPEND configopts ${i}) + if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") + list(APPEND includes "${${i}}") + else() + set(found FALSE) + set(missing_headers TRUE) + endif() + endforeach() + + # Process all libraries and set found false if any are missing + foreach (i ${libraryopts}) + list(APPEND configopts ${i}) + if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") + list(APPEND libs "${${i}}") + else() + set (found FALSE) + endif() + endforeach() + + # Version checks + if (found AND findver) + if (NOT version) + message(WARNING "The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.") + elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver)) + set(found FALSE) + set(version_unsuitable TRUE) + endif() + endif() + + # If all-OK, hide all config options, export variables, print status and exit + if (found) + foreach (i ${configopts}) + mark_as_advanced(${i}) + endforeach() + if (NOT quiet) + message(STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") + if (LIBFIND_DEBUG) + message(STATUS " ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}") + message(STATUS " ${PREFIX}_INCLUDE_OPTS=${includeopts}") + message(STATUS " ${PREFIX}_INCLUDE_DIRS=${includes}") + message(STATUS " ${PREFIX}_LIBRARY_OPTS=${libraryopts}") + message(STATUS " ${PREFIX}_LIBRARIES=${libs}") + endif() + set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE) + set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE) + set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE) + set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE) + set (${PREFIX}_FOUND TRUE PARENT_SCOPE) + endif() + return() + endif() + + # Format messages for debug info and the type of error + set(vars "Relevant CMake configuration variables:\n") + foreach (i ${configopts}) + mark_as_advanced(CLEAR ${i}) + set(val ${${i}}) + if ("${val}" STREQUAL "${i}-NOTFOUND") + set (val "") + elseif (val AND NOT EXISTS ${val}) + set (val "${val} (does not exist)") + else() + set(some_files TRUE) + endif() + set(vars "${vars} ${i}=${val}\n") + endforeach() + set(vars "${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\n") + if (version_unsuitable) + set(msg "${PREFIX} ${${PREFIX}_VERSION} was found but") + if (exactver) + set(msg "${msg} only version ${findver} is acceptable.") + else() + set(msg "${msg} version ${findver} is the minimum requirement.") + endif() + else() + if (missing_headers) + set(msg "We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?") + elseif (some_files) + set(msg "We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?") + if(findver) + set(msg "${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).") + endif() + else() + set(msg "We were unable to find package ${PREFIX}.") + endif() + endif() + + # Fatal error out if REQUIRED + if (required) + set(msg "REQUIRED PACKAGE NOT FOUND\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.") + message(FATAL_ERROR "${msg}\n${vars}") + endif() + # Otherwise just print a nasty warning + if (NOT quiet) + message(WARNING "WARNING: MISSING PACKAGE\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \n${vars}") + endif() +endfunction() + diff --git a/Microsoft.WindowsAzure.Storage/includes/targetver.h b/Microsoft.WindowsAzure.Storage/includes/targetver.h index 9a67c656..0f73f169 100644 --- a/Microsoft.WindowsAzure.Storage/includes/targetver.h +++ b/Microsoft.WindowsAzure.Storage/includes/targetver.h @@ -22,4 +22,6 @@ // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. +#ifdef WIN32 #include +#endif diff --git a/Microsoft.WindowsAzure.Storage/includes/was/blob.h b/Microsoft.WindowsAzure.Storage/includes/was/blob.h index 0e36533f..8beaf537 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/blob.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/blob.h @@ -254,7 +254,7 @@ namespace azure { namespace storage { enum class delete_snapshots_option { /// - /// Delete blobs but not snapshots. + /// Delete the blob only. If the blob has snapshots, this option will result in an error from the service. /// none, @@ -997,21 +997,44 @@ namespace azure { namespace storage { /// cloud_blob_properties() : m_type(blob_type::unspecified), m_page_blob_sequence_number(0), - m_lease_state(lease_state::unspecified), m_lease_status(lease_status::unspecified), - m_lease_duration(lease_duration::unspecified), m_size(0) + m_lease_state(azure::storage::lease_state::unspecified), m_lease_status(azure::storage::lease_status::unspecified), + m_lease_duration(azure::storage::lease_duration::unspecified), m_size(0) { } + cloud_blob_properties(const cloud_blob_properties& other) + { + *this = other; + } + /// /// Initializes a new instance of the class. /// /// A reference to a set of on which to base the new instance. cloud_blob_properties(cloud_blob_properties&& other) { - // TODO: Double check that the following std::move call is needed *this = std::move(other); } + cloud_blob_properties& operator=(const cloud_blob_properties& other) + { + m_size = other.m_size; + m_etag = other.m_etag; + m_last_modified = other.m_last_modified; + m_type = other.m_type; + m_lease_duration = other.m_lease_duration; + m_lease_state = other.m_lease_state; + m_lease_status = other.m_lease_status; + m_page_blob_sequence_number = other.m_page_blob_sequence_number; + m_cache_control = other.m_cache_control; + m_content_disposition = other.m_content_disposition; + m_content_encoding = other.m_content_encoding; + m_content_language = other.m_content_language; + m_content_md5 = other.m_content_md5; + m_content_type = other.m_content_type; + return *this; + } + /// /// Returns a reference to a object. /// @@ -1603,7 +1626,7 @@ namespace azure { namespace storage { /// /// The block name. /// A value that indicates which block lists to search for the block. - block_list_item(utility::string_t& id, block_mode mode) + block_list_item(utility::string_t id, block_mode mode) : m_id(std::move(id)), m_size(std::numeric_limits::max()), m_mode(mode) { } @@ -1784,9 +1807,8 @@ namespace azure { namespace storage { private: sequence_number(sequence_number_action action, int64_t value) + : m_action(action), m_value(value) { - m_action = action; - m_value = value; } sequence_number_action m_action; @@ -1802,7 +1824,11 @@ namespace azure { namespace storage { /// /// Initializes a new instance of the class. /// - cloud_blob_container_properties() {} + cloud_blob_container_properties() + : m_lease_status(azure::storage::lease_status::unspecified), m_lease_state(azure::storage::lease_state::unspecified), + m_lease_duration(azure::storage::lease_duration::unspecified) + { + } /// /// Initializes a new instance of the class. @@ -2237,7 +2263,7 @@ namespace azure { namespace storage { void initialize() { - set_authentication_scheme(authentication_scheme::shared_key); + set_authentication_scheme(azure::storage::authentication_scheme::shared_key); m_directory_delimiter = protocol::directory_delimiter; } diff --git a/Microsoft.WindowsAzure.Storage/includes/was/common.h b/Microsoft.WindowsAzure.Storage/includes/was/common.h index d7dfee44..d1b402b4 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/common.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/common.h @@ -22,6 +22,12 @@ #include "core.h" #include "retry_policies.h" +#ifndef WIN32 +#include +#include +#include +#endif + namespace azure { namespace storage { namespace protocol @@ -150,7 +156,7 @@ namespace azure { namespace storage { /// Gets the continuation token used to retrieve the next segment of results. /// /// The continuation token. - const continuation_token& continuation_token() const + const azure::storage::continuation_token& continuation_token() const { return m_continuation_token; } @@ -1052,6 +1058,15 @@ namespace azure { namespace storage { return m_user_headers; } + /// + /// Gets the user headers provided for the request. + /// + /// A object containing user headers. + const web::http::http_headers& user_headers() const + { + return m_user_headers; + } + /// /// Gets the results of the request. /// @@ -1111,6 +1126,35 @@ namespace azure { namespace storage { m_response_received = value; } +#ifndef WIN32 + /// + /// Gets the logger object on this op_context. + /// + /// The logger object used by this op_context. + boost::log::sources::severity_logger& logger() + { + return m_logger; + } + + /// + /// Gets the logger object on this op_context. + /// + /// The logger object used by this op_context. + const boost::log::sources::severity_logger& logger() const + { + return m_logger; + } + + /// + /// Sets the logger object on this op_context. + /// + /// The logger object to use for requests made by this op_context. + void set_logger(boost::log::sources::severity_logger logger) + { + m_logger = std::move(logger); + } +#endif + private: std::function m_sending_request; @@ -1122,6 +1166,9 @@ namespace azure { namespace storage { client_log_level m_log_level; std::vector m_request_results; pplx::extensibility::critical_section_t m_request_results_lock; +#ifndef WIN32 + boost::log::sources::severity_logger m_logger; +#endif }; /// @@ -1249,6 +1296,15 @@ namespace azure { namespace storage { return m_impl->user_headers(); } + /// + /// Gets or sets additional headers on the request, for example, for proxy or logging information. + /// + /// A reference containing additional header information. + const web::http::http_headers& user_headers() const + { + return m_impl->user_headers(); + } + /// /// Gets the set of request results that the current operation has created. /// @@ -1278,6 +1334,35 @@ namespace azure { namespace storage { m_impl->set_response_received(value); } +#ifndef WIN32 + /// + /// Gets the logger object on this op_context. + /// + /// The logger object used by this op_context. + boost::log::sources::severity_logger& logger() + { + return m_impl->logger(); + } + + /// + /// Gets the logger object on this op_context. + /// + /// The logger object used by this op_context. + const boost::log::sources::severity_logger& logger() const + { + return m_impl->logger(); + } + + /// + /// Sets the logger object on this op_context. + /// + /// The logger object to use for requests made by this op_context. + void set_logger(boost::log::sources::severity_logger logger) + { + m_impl->set_logger(std::move(logger)); + } +#endif + std::shared_ptr<_operation_context> _get_impl() const { return m_impl; @@ -1632,6 +1717,30 @@ namespace azure { namespace storage { m_location_mode = location_mode; } + /// + /// Gets the number of bytes to buffer when reading from and writing to a network stream. + /// + /// The number of bytes to buffer when reading from and writing to a network stream. + /// + /// Using a larger buffer size is more efficient when downloading and uploading larger blobs because it will reduce CPU usage. + /// + size_t http_buffer_size() const + { + return m_http_buffer_size; + } + + /// + /// Sets the number of bytes to buffer when reading from and writing to a network stream. + /// + /// The number of bytes to buffer when reading from and writing to a network stream. + /// + /// Using a larger buffer size is more efficient when downloading and uploading larger blobs because it will reduce CPU usage. + /// + void set_http_buffer_size(size_t http_buffer_size) + { + m_http_buffer_size = http_buffer_size; + } + /// /// Gets the expiry time across all potential retries for the request. /// @@ -1646,11 +1755,7 @@ namespace azure { namespace storage { /// /// Initializes a new instance of the class. /// - request_options() - : m_location_mode(location_mode::primary_only), - m_retry_policy(exponential_retry_policy()) - { - } + WASTORAGE_API request_options(); /// /// Applies the default set of request options. @@ -1668,6 +1773,7 @@ namespace azure { namespace storage { m_server_timeout.merge(other.m_server_timeout); m_maximum_execution_time.merge(other.m_maximum_execution_time); m_location_mode.merge(other.m_location_mode); + m_http_buffer_size.merge(other.m_http_buffer_size); if (apply_expiry) { @@ -1690,6 +1796,7 @@ namespace azure { namespace storage { option_with_default m_server_timeout; option_with_default m_maximum_execution_time; option_with_default m_location_mode; + option_with_default m_http_buffer_size; }; }} // namespace azure::storage diff --git a/Microsoft.WindowsAzure.Storage/includes/was/core.h b/Microsoft.WindowsAzure.Storage/includes/was/core.h index 8301ac20..c557bda8 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/core.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/core.h @@ -355,7 +355,7 @@ namespace azure { namespace storage { /// The fallback value. void merge(const option_with_default& value, const T& fallback_value) { - merge(value.m_has_value ? value : fallback_value); + merge(value.m_has_value ? (const T&)value : fallback_value); } private: @@ -437,7 +437,8 @@ namespace azure { namespace storage { request_result() : m_is_response_available(false), m_target_location(storage_location::unspecified), - m_http_status_code(0) + m_http_status_code(0), + m_content_length(-1) { } @@ -451,7 +452,8 @@ namespace azure { namespace storage { m_start_time(start_time), m_target_location(target_location), m_end_time(utility::datetime::utc_now()), - m_http_status_code(0) + m_http_status_code(0), + m_content_length(-1) { } @@ -547,9 +549,18 @@ namespace azure { namespace storage { } /// - /// Gets the content-MD5 hash for the request. + /// Gets the content length for the request. /// - /// The content-MD5 hash for the request. + /// The content length for the request. + utility::size64_t content_length() const + { + return m_content_length; + } + + /// + /// Gets the content MD5 hash for the request. + /// + /// The content MD5 hash for the request. const utility::string_t& content_md5() const { return m_content_md5; @@ -594,6 +605,7 @@ namespace azure { namespace storage { web::http::status_code m_http_status_code; utility::string_t m_service_request_id; utility::datetime m_request_date; + utility::size64_t m_content_length; utility::string_t m_content_md5; utility::string_t m_etag; storage_extended_error m_extended_error; @@ -670,47 +682,47 @@ namespace azure { namespace storage { } /// - /// Gets the target location for the next retry. + /// Gets the number of retries for the given operation. /// - /// The target location for the next retry. - storage_location next_location() const + /// The number of retries for the given operation. + int current_retry_count() const { - return m_next_location; + return m_current_retry_count; } /// - /// Gets the location mode for subsequent retries. + /// Gets the results of the last request. /// - /// The location mode for subsequent retries. - location_mode current_location_mode() const + /// A object that represents the results of the last request. + const request_result& last_request_result() const { - return m_current_location_mode; + return m_last_request_result; } /// - /// Gets the number of retries for the given operation. + /// Gets the target location for the next retry. /// - /// The number of retries for the given operation. - int current_retry_count() const + /// The target location for the next retry. + storage_location next_location() const { - return m_current_retry_count; + return m_next_location; } /// - /// Gets the results of the last request. + /// Gets the location mode for subsequent retries. /// - /// A object that represents the results of the last request. - const request_result& last_request_result() const + /// The location mode for subsequent retries. + location_mode current_location_mode() const { - return m_last_request_result; + return m_current_location_mode; } private: - storage_location m_next_location; - location_mode m_current_location_mode; int m_current_retry_count; request_result m_last_request_result; + storage_location m_next_location; + location_mode m_current_location_mode; }; /// @@ -724,7 +736,8 @@ namespace azure { namespace storage { /// Initializes a new instance of the class. /// retry_info() - : m_should_retry(false) + : m_should_retry(false), m_target_location(storage_location::unspecified), + m_updated_location_mode(location_mode::unspecified), m_retry_interval() { } @@ -733,13 +746,20 @@ namespace azure { namespace storage { /// /// The object that was passed in to the retry policy. explicit retry_info(const retry_context& context) - : m_should_retry(true), - m_target_location(context.next_location()), - m_updated_location_mode(context.current_location_mode()), - m_retry_interval(protocol::default_retry_interval) + : m_should_retry(true), m_target_location(context.next_location()), + m_updated_location_mode(context.current_location_mode()), m_retry_interval(protocol::default_retry_interval) { } + /// + /// Indicates that the request should be retried. + /// + /// true if the request should be retried. + bool should_retry() const + { + return m_should_retry; + } + /// /// Gets the target location for the next retry. /// @@ -794,21 +814,12 @@ namespace azure { namespace storage { m_retry_interval = value; } - /// - /// Indicates that the request should be retried. - /// - /// true if the request should be retried. - bool should_retry() const - { - return m_should_retry; - } - private: bool m_should_retry; - std::chrono::milliseconds m_retry_interval; storage_location m_target_location; location_mode m_updated_location_mode; + std::chrono::milliseconds m_retry_interval; }; class retry_policy; @@ -885,3 +896,7 @@ namespace azure { namespace storage { }; }} // namespace azure::storage + +#ifndef WIN32 +#define UNREFERENCED_PARAMETER(P) (P) +#endif diff --git a/Microsoft.WindowsAzure.Storage/includes/was/queue.h b/Microsoft.WindowsAzure.Storage/includes/was/queue.h index 09cfe305..2c3be2eb 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/queue.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/queue.h @@ -707,7 +707,7 @@ namespace azure { namespace storage { void initialize() { - set_authentication_scheme(authentication_scheme::shared_key); + set_authentication_scheme(azure::storage::authentication_scheme::shared_key); } queue_request_options get_modified_options(const queue_request_options& options) const; diff --git a/Microsoft.WindowsAzure.Storage/includes/was/retry_policies.h b/Microsoft.WindowsAzure.Storage/includes/was/retry_policies.h index e3d106fb..d3fe4434 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/retry_policies.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/retry_policies.h @@ -179,7 +179,7 @@ namespace azure { namespace storage { /// The maximum number of retries to attempt. basic_exponential_retry_policy(std::chrono::seconds delta_backoff, int max_attempts) : basic_common_retry_policy(max_attempts), m_delta_backoff(delta_backoff), - m_rand_distribution(delta_backoff.count() * 0.8, delta_backoff.count() * 1.2) + m_rand_distribution(static_cast(delta_backoff.count()) * 0.8, static_cast(delta_backoff.count()) * 1.2) { } diff --git a/Microsoft.WindowsAzure.Storage/includes/was/service_client.h b/Microsoft.WindowsAzure.Storage/includes/was/service_client.h index a1322771..ea6820e1 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/service_client.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/service_client.h @@ -81,6 +81,7 @@ namespace azure { namespace storage { /// Initializes a new instance of the service client class using the specified service endpoint. /// cloud_client() + : m_authentication_scheme(azure::storage::authentication_scheme::shared_key) { } @@ -89,7 +90,7 @@ namespace azure { namespace storage { /// /// A object containing the service endpoint for all locations. explicit cloud_client(storage_uri base_uri) - : m_base_uri(std::move(base_uri)) + : m_base_uri(std::move(base_uri)), m_authentication_scheme(azure::storage::authentication_scheme::shared_key) { } @@ -99,7 +100,7 @@ namespace azure { namespace storage { /// A object containing the service endpoint for all locations. /// The to use. cloud_client(storage_uri base_uri, azure::storage::storage_credentials credentials) - : m_base_uri(std::move(base_uri)), m_credentials(std::move(credentials)) + : m_base_uri(std::move(base_uri)), m_credentials(std::move(credentials)), m_authentication_scheme(azure::storage::authentication_scheme::shared_key) { } diff --git a/Microsoft.WindowsAzure.Storage/includes/was/table.h b/Microsoft.WindowsAzure.Storage/includes/was/table.h index c815e78c..0be976e9 100644 --- a/Microsoft.WindowsAzure.Storage/includes/was/table.h +++ b/Microsoft.WindowsAzure.Storage/includes/was/table.h @@ -1054,17 +1054,17 @@ namespace azure { namespace storage { /// /// Represents the And operator. /// - WASTORAGE_API const static utility::string_t and; + WASTORAGE_API const static utility::string_t op_and; /// /// Represents the Not operator. /// - WASTORAGE_API const static utility::string_t not; + WASTORAGE_API const static utility::string_t op_not; /// /// Represents the Or operator. /// - WASTORAGE_API const static utility::string_t or; + WASTORAGE_API const static utility::string_t op_or; }; /// @@ -1794,7 +1794,7 @@ namespace azure { namespace storage { void initialize() { - set_authentication_scheme(authentication_scheme::shared_key); + set_authentication_scheme(azure::storage::authentication_scheme::shared_key); } table_request_options get_modified_options(const table_request_options& options) const; diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/basic_types.h b/Microsoft.WindowsAzure.Storage/includes/wascore/basic_types.h index 2f7adde4..c345e254 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/basic_types.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/basic_types.h @@ -53,7 +53,10 @@ namespace utility { #ifdef WIN32 typedef UUID uuid; #else - typedef uuid_t uuid; + typedef struct + { + uuid_t data; + } uuid; #endif /// diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/blobstreams.h b/Microsoft.WindowsAzure.Storage/includes/wascore/blobstreams.h index a76701f4..148500ad 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/blobstreams.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/blobstreams.h @@ -37,7 +37,7 @@ namespace azure { namespace storage { namespace core { { if (!options.disable_content_md5_validation() && !m_blob->properties().content_md5().empty()) { - m_blob_hash = hash_md5_streambuf(); + m_blob_hash_provider = hash_provider::create_md5_hash_provider(); } } @@ -156,7 +156,7 @@ namespace azure { namespace storage { namespace core { access_condition m_condition; blob_request_options m_options; operation_context m_context; - hash_streambuf m_blob_hash; + hash_provider m_blob_hash_provider; off_type m_current_blob_offset; off_type m_next_blob_offset; size_t m_buffer_size; @@ -185,12 +185,12 @@ namespace azure { namespace storage { namespace core { { if (options.use_transactional_md5()) { - m_block_hash = hash_md5_streambuf(); + m_block_hash_provider = hash_provider::create_md5_hash_provider(); } if (options.store_blob_content_md5()) { - m_blob_hash = hash_md5_streambuf(); + m_blob_hash_provider = hash_provider::create_md5_hash_provider(); } } @@ -307,15 +307,17 @@ namespace azure { namespace storage { namespace core { private: - concurrency::streams::istream m_stream; + // Note: m_size must be initialized before m_stream, and thus must be listed first in this list. + // This is because we use std::move to initialize m_stream, but we need to get the size first. utility::size64_t m_size; utility::string_t m_content_md5; + concurrency::streams::istream m_stream; }; concurrency::streams::container_buffer> m_buffer; pos_type m_current_streambuf_offset; - hash_streambuf m_blob_hash; - hash_streambuf m_block_hash; + hash_provider m_blob_hash_provider; + hash_provider m_block_hash_provider; access_condition m_condition; blob_request_options m_options; operation_context m_context; diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h b/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h index 6c575e9c..76ba5baa 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/constants.h @@ -35,6 +35,13 @@ namespace azure { namespace storage { namespace protocol { // duration constants const std::chrono::seconds default_retry_interval(3); + // The following value must be less than 2147482, which is the highest + // that Casablanca 2.2.0 on Linux can accept, which is derived from + // the maximum value for a signed long on g++, divided by 1000. + // Choosing to set it to 24 days to align with .NET. + const std::chrono::seconds default_maximum_execution_time(24 * 24 * 60 * 60); + // For the following value, "0" means "don't send a timeout to the service" + const std::chrono::seconds default_server_timeout(0); // uri query parameters const utility::string_t uri_query_timeout(U("timeout")); @@ -298,9 +305,9 @@ namespace azure { namespace storage { namespace protocol { // user agent #if defined(WIN32) - const utility::string_t header_value_user_agent(U("Azure-Storage/0.3.0 (Native; Windows)")); + const utility::string_t header_value_user_agent(U("Azure-Storage/0.4.0 (Native; Windows)")); #else - const utility::string_t header_value_user_agent(U("Azure-Storage/0.3.0 (Native)")); + const utility::string_t header_value_user_agent(U("Azure-Storage/0.4.0 (Native)")); #endif }}} // namespace azure::storage::protocol diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/executor.h b/Microsoft.WindowsAzure.Storage/includes/wascore/executor.h index 29ac3da2..26418da1 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/executor.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/executor.h @@ -24,6 +24,7 @@ #include "util.h" #include "streams.h" #include "was/auth.h" +#include "wascore/resources.h" namespace azure { namespace storage { namespace core { @@ -48,32 +49,23 @@ namespace azure { namespace storage { namespace core { return pplx::task_from_result(istream_descriptor(stream, length, utility::string_t())); } + hash_provider provider = calculate_md5 ? core::hash_provider::create_md5_hash_provider() : core::hash_provider(); concurrency::streams::container_buffer> temp_buffer; concurrency::streams::ostream temp_stream; - hash_streambuf hash_buffer; if (calculate_md5) { - // If MD5 is needed, a splitter_streambuf will act as a proxy to forward incoming data to - // a hash_md5_streambuf and the in-memory container_buffer - hash_buffer = hash_md5_streambuf(); - temp_stream = splitter_streambuf(temp_buffer, hash_buffer).create_ostream(); + temp_stream = hash_wrapper_streambuf(temp_buffer, provider).create_ostream(); } else { temp_stream = temp_buffer.create_ostream(); } - return stream_copy_async(stream, temp_stream, length).then([temp_buffer, hash_buffer] (pplx::task buffer_task) mutable -> istream_descriptor + return stream_copy_async(stream, temp_stream, length).then([temp_buffer, provider] (pplx::task buffer_task) mutable -> istream_descriptor { - utility::string_t md5; - if (hash_buffer) - { - hash_buffer.close().wait(); - md5 = utility::conversions::to_base64(hash_buffer.hash()); - } - - return istream_descriptor(concurrency::streams::container_stream>::open_istream(temp_buffer.collection()), buffer_task.get(), md5); + provider.close(); + return istream_descriptor(concurrency::streams::container_stream>::open_istream(temp_buffer.collection()), buffer_task.get(), provider.hash()); }); } @@ -185,12 +177,12 @@ namespace azure { namespace storage { namespace core { m_calculate_response_body_md5 = value; } - void set_build_request(std::function value) + void set_build_request(std::function value) { m_build_request = value; } - void set_custom_sign_request(std::function value) + void set_custom_sign_request(std::function value) { m_sign_request = value; } @@ -200,17 +192,17 @@ namespace azure { namespace storage { namespace core { set_custom_sign_request(std::bind(&protocol::authentication_handler::sign_request, handler, std::placeholders::_1, std::placeholders::_2)); } - void set_recover_request(std::function value) + void set_recover_request(std::function value) { m_recover_request = value; } - void set_preprocess_response(std::function value) + void set_preprocess_response(std::function value) { m_preprocess_response = value; } - void set_postprocess_response(std::function (const web::http::http_response &, const request_result&, const ostream_descriptor&, operation_context)> value) + void set_postprocess_response(std::function(const web::http::http_response &, const request_result&, const ostream_descriptor&, operation_context)> value) { m_postprocess_response = value; } @@ -252,10 +244,10 @@ namespace azure { namespace storage { namespace core { command_location_mode m_location_mode; std::function m_build_request; - std::function m_sign_request; - std::function m_recover_request; - std::function m_preprocess_response; - std::function (const web::http::http_response &, const request_result&, const ostream_descriptor&, operation_context)> m_postprocess_response; + std::function m_sign_request; + std::function m_recover_request; + std::function m_preprocess_response; + std::function (const web::http::http_response&, const request_result&, const ostream_descriptor&, operation_context)> m_postprocess_response; friend class executor; }; @@ -266,8 +258,8 @@ namespace azure { namespace storage { namespace core { public: executor(std::shared_ptr> command, const request_options& options, operation_context context) - : m_command(command), m_request_options(options), m_context(context), - m_retry_count(0), m_current_location(get_first_location(options.location_mode())), + : m_command(command), m_request_options(options), m_context(context), m_is_hashing_started(false), + m_total_downloaded(0), m_retry_count(0), m_current_location(get_first_location(options.location_mode())), m_current_location_mode(options.location_mode()), m_retry_policy(options.retry_policy().clone()) { } @@ -283,7 +275,7 @@ namespace azure { namespace storage { namespace core { // TODO: Reduce usage of auto variable types auto instance = std::make_shared>(command, options, context); - return pplx::details::do_while([instance] () -> pplx::task + return pplx::details::do_while([instance]() -> pplx::task { // 0. Begin request instance->validate_location_mode(); @@ -320,24 +312,34 @@ namespace azure { namespace storage { namespace core { instance->m_command->m_request_body.rewind(); instance->m_request.set_body(instance->m_command->m_request_body.stream(), instance->m_command->m_request_body.length(), utility::string_t()); } + else + { + // TODO: Remove the following when we can take a dependency on Casablanca 2.3. This line fo code is a workaround for a bug in 2.2. + if ((((utility::string_t)instance->m_request.method()) == U("HEAD")) || (((utility::string_t)instance->m_request.method()) == U("DELETE")) || (((utility::string_t)instance->m_request.method()) == U("GET"))) + { + instance->m_request.headers().add(protocol::xml_content_length, 0); + } + } // If the command wants to copy the response body to a stream, set it // on the http_request object if (instance->m_command->m_destination_stream) { - // If MD5 is needed, a splitter_streambuf will act as a proxy to forward incoming data to - // a hash_md5_streambuf and the destination stream provided by the command - if (instance->m_command->m_calculate_response_body_md5) + // Calculate the length and MD5 hash if needed as the incoming data is read + if (!instance->m_is_hashing_started) { - instance->m_hash_streambuf = hash_md5_streambuf(); - instance->m_response_streambuf = splitter_streambuf(instance->m_command->m_destination_stream.streambuf(), instance->m_hash_streambuf); - } - else - { - instance->m_hash_streambuf = hash_streambuf(); - instance->m_response_streambuf = splitter_streambuf(instance->m_command->m_destination_stream.streambuf(), null_streambuf()); + if (instance->m_command->m_calculate_response_body_md5) + { + instance->m_hash_provider = hash_provider::create_md5_hash_provider(); + } + + instance->m_total_downloaded = 0; + instance->m_is_hashing_started = true; + + // TODO: Consider using hash_provider::is_enabled instead of m_is_hashing_started to signal when the hash provider has been closed } + instance->m_response_streambuf = hash_wrapper_streambuf(instance->m_command->m_destination_stream.streambuf(), instance->m_hash_provider); instance->m_request.set_response_stream(instance->m_response_streambuf.create_ostream()); } @@ -351,13 +353,27 @@ namespace azure { namespace storage { namespace core { // 3. Sign Request instance->m_command->m_sign_request(instance->m_request, instance->m_context); - // 4. Set timeout + // 4. Set HTTP client configuration web::http::client::http_client_config config; config.set_timeout(instance->remaining_time()); + // TODO: Remove the following when we can take a dependency on Casablanca 2.3. This line fo code is a workaround for a bug in 2.2. +#ifndef WIN32 + if (config.timeout() < std::chrono::seconds(1)) + { + config.set_timeout(std::chrono::seconds(1)); + } +#endif + + size_t http_buffer_size = instance->m_request_options.http_buffer_size(); + if (http_buffer_size > 0) + { + config.set_chunksize(http_buffer_size); + } + // 5-6. Potentially upload data and get response web::http::client::http_client client(instance->m_request.request_uri().authority(), config); - return client.request(instance->m_request).then([instance] (pplx::task get_headers_task) -> pplx::task + return client.request(instance->m_request).then([instance](pplx::task get_headers_task) -> pplx::task { // Headers are ready. It should be noted that http_client will // continue to download the response body in parallel. @@ -382,8 +398,8 @@ namespace azure { namespace storage { namespace core { // 7. Do Response parsing (headers etc, no stream available here) // This is when the status code will be checked and m_preprocess_response // will throw a storage_exception if it is not expected. - instance->m_result = instance->m_command->m_preprocess_response(response, instance->m_context); instance->m_request_result = request_result(instance->m_start_time, instance->m_current_location, response, false); + instance->m_result = instance->m_command->m_preprocess_response(response, instance->m_request_result, instance->m_context); if (logger::instance().should_log(instance->m_context, client_log_level::log_level_informational)) { @@ -407,7 +423,7 @@ namespace azure { namespace storage { namespace core { // is seekable and thus it cannot be read back to parse the error. if (!instance->m_command->m_destination_stream) { - return response.content_ready().then([instance] (pplx::task get_error_body_task) -> web::http::http_response + return response.content_ready().then([instance](pplx::task get_error_body_task) -> web::http::http_response { auto response = get_error_body_task.get(); instance->m_request_result = request_result(instance->m_start_time, instance->m_current_location, response, true); @@ -424,11 +440,22 @@ namespace azure { namespace storage { namespace core { // In the worst case, storage_exception will just contain the HTTP error message throw storage_exception(utility::conversions::to_utf8string(response.reason_phrase())); } - }).then([instance] (pplx::task get_body_task) -> pplx::task + }).then([instance](pplx::task get_body_task) -> pplx::task { // 9. Evaluate response & parse results auto response = get_body_task.get(); + if (instance->m_command->m_destination_stream) + { + utility::size64_t current_total_downloaded = instance->m_response_streambuf.total_written(); + utility::size64_t content_length = instance->m_request_result.content_length(); + if (content_length != -1 && current_total_downloaded != content_length) + { + // The download was interrupted before it could complete + throw storage_exception(protocol::error_incorrect_length); + } + } + // If the command asked for post-processing, it is now time to call m_postprocess_response if (instance->m_command->m_postprocess_response) { @@ -437,22 +464,18 @@ namespace azure { namespace storage { namespace core { logger::instance().log(instance->m_context, client_log_level::log_level_informational, U("Processing response body")); } - // Get the MD5 hash if MD5 was calculated. - utility::string_t md5; - if (instance->m_hash_streambuf) - { - // It is ok to wait this call, as all hash_streambuf implementations are synchronous anyway. - instance->m_hash_streambuf.close().wait(); - md5 = utility::conversions::to_base64(instance->m_hash_streambuf.hash()); - } + // Finish the MD5 hash if MD5 was being calculated + instance->m_hash_provider.close(); + instance->m_is_hashing_started = false; ostream_descriptor descriptor; if (instance->m_response_streambuf) { - descriptor = ostream_descriptor(instance->m_response_streambuf.total_written(), md5); + utility::size64_t total_downloaded = instance->m_total_downloaded + instance->m_response_streambuf.total_written(); + descriptor = ostream_descriptor(total_downloaded, instance->m_hash_provider.hash()); } - return instance->m_command->m_postprocess_response(response, instance->m_request_result, descriptor, instance->m_context).then([instance] (pplx::task result_task) + return instance->m_command->m_postprocess_response(response, instance->m_request_result, descriptor, instance->m_context).then([instance](pplx::task result_task) { try { @@ -475,7 +498,7 @@ namespace azure { namespace storage { namespace core { { return pplx::task_from_result(); } - }).then([instance] (pplx::task final_task) -> pplx::task + }).then([instance](pplx::task final_task) -> pplx::task { bool retryable_exception = true; instance->m_context._get_impl()->add_request_result(instance->m_request_result); @@ -525,10 +548,15 @@ namespace azure { namespace storage { namespace core { instance->m_current_location = retry.target_location(); instance->m_current_location_mode = retry.updated_location_mode(); + if (instance->m_response_streambuf) + { + instance->m_total_downloaded += instance->m_response_streambuf.total_written(); + } + // Try to recover the request. If it cannot be recovered, it cannot be retried // even if the retry policy allowed for a retry. if (instance->m_command->m_recover_request && - !instance->m_command->m_recover_request(instance->m_context)) + !instance->m_command->m_recover_request(instance->m_total_downloaded, instance->m_context)) { if (logger::instance().should_log(instance->m_context, client_log_level::log_level_error)) { @@ -545,7 +573,7 @@ namespace azure { namespace storage { namespace core { logger::instance().log(instance->m_context, client_log_level::log_level_informational, str.str()); } - return complete_after(retry.retry_interval()).then([] () -> bool + return complete_after(retry.retry_interval()).then([]() -> bool { // Returning true here will tell the outer do_while loop to loop one more time. return true; @@ -555,7 +583,7 @@ namespace azure { namespace storage { namespace core { // Returning false here will cause do_while to exit. return pplx::task_from_result(false); }); - }).then([instance] (pplx::task loop_task) -> T + }).then([instance](pplx::task loop_task) -> T { instance->m_context.set_end_time(utility::datetime::utc_now()); loop_task.wait(); @@ -690,8 +718,10 @@ namespace azure { namespace storage { namespace core { web::http::uri_builder m_uri_builder; web::http::http_request m_request; request_result m_request_result; - hash_streambuf m_hash_streambuf; - splitter_streambuf m_response_streambuf; + bool m_is_hashing_started; + hash_provider m_hash_provider; + hash_wrapper_streambuf m_response_streambuf; + utility::size64_t m_total_downloaded; retry_policy m_retry_policy; int m_retry_count; storage_location m_current_location; @@ -712,11 +742,11 @@ namespace azure { namespace storage { namespace core { { } - void set_preprocess_response(std::function value) + void set_preprocess_response(std::function value) { - storage_command::set_preprocess_response([value] (const web::http::http_response& response, operation_context context) -> void_command_type + storage_command::set_preprocess_response([value] (const web::http::http_response& response, const request_result& result, operation_context context) -> void_command_type { - value(response, context); + value(response, result, context); return VOID_COMMAND_RESULT; }); } diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/hashing.h b/Microsoft.WindowsAzure.Storage/includes/wascore/hashing.h new file mode 100644 index 00000000..5463942c --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/hashing.h @@ -0,0 +1,268 @@ +// ----------------------------------------------------------------------------------------- +// +// 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. +// +// ----------------------------------------------------------------------------------------- + +#pragma once + +#include "cpprest/streams.h" + +#include "wascore/basic_types.h" +#include "was/core.h" + +#ifdef WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#endif +#define NOMINMAX +#include +#include +#include +#else +#include +#include +#include +#endif + +namespace azure { namespace storage { namespace core { + + class hash_provider_impl + { + public: + virtual ~hash_provider_impl() + { + } + + virtual bool is_enabled() const = 0; + virtual void write(const uint8_t* data, size_t count) = 0; + virtual void close() = 0; + virtual utility::string_t hash() const = 0; + }; + +#ifdef WIN32 + + class cryptography_hash_algorithm + { + public: + ~cryptography_hash_algorithm(); + + operator BCRYPT_ALG_HANDLE() const + { + return m_algorithm_handle; + } + + protected: + cryptography_hash_algorithm(LPCWSTR algorithm_id, ULONG flags); + + private: + BCRYPT_ALG_HANDLE m_algorithm_handle; + }; + + class hmac_sha256_hash_algorithm : public cryptography_hash_algorithm + { + public: + static const hmac_sha256_hash_algorithm& instance() + { + return m_instance; + } + + private: + hmac_sha256_hash_algorithm() + : cryptography_hash_algorithm(BCRYPT_SHA256_ALGORITHM, BCRYPT_ALG_HANDLE_HMAC_FLAG) + { + } + + static hmac_sha256_hash_algorithm m_instance; + }; + + class md5_hash_algorithm : public cryptography_hash_algorithm + { + public: + static const md5_hash_algorithm& instance() + { + return m_instance; + } + + private: + md5_hash_algorithm() + : cryptography_hash_algorithm(BCRYPT_MD5_ALGORITHM, 0) + { + } + + static md5_hash_algorithm m_instance; + }; + + class cryptography_hash_provider_impl : public hash_provider_impl + { + public: + cryptography_hash_provider_impl(const cryptography_hash_algorithm& algorithm, const std::vector& key); + ~cryptography_hash_provider_impl() override; + + bool is_enabled() const override + { + return true; + } + + void write(const uint8_t* data, size_t count) override; + void close() override; + + utility::string_t hash() const override + { + return utility::conversions::to_base64(m_hash); + } + + private: + std::vector m_hash_object; + BCRYPT_HASH_HANDLE m_hash_handle; + std::vector m_hash; + }; + + class hmac_sha256_hash_provider_impl : public cryptography_hash_provider_impl + { + public: + hmac_sha256_hash_provider_impl(const std::vector& key); + }; + + class md5_hash_provider_impl : public cryptography_hash_provider_impl + { + public: + md5_hash_provider_impl(); + }; + +#else // Linux + + class cryptography_hash_provider_impl : public hash_provider_impl + { + public: + ~cryptography_hash_provider_impl() override + { + } + + bool is_enabled() const override + { + return true; + } + + utility::string_t hash() const override + { + return utility::conversions::to_base64(m_hash); + } + + protected: + std::vector m_hash; + }; + + class hmac_sha256_hash_provider_impl : public cryptography_hash_provider_impl + { + public: + hmac_sha256_hash_provider_impl(const std::vector& key); + + void write(const uint8_t* data, size_t count) override; + void close() override; + + private: + HMAC_CTX m_hash_context; + }; + + class md5_hash_provider_impl : public cryptography_hash_provider_impl + { + public: + md5_hash_provider_impl(); + + void write(const uint8_t* data, size_t count) override; + void close() override; + + private: + MD5_CTX m_hash_context; + }; + +#endif + + class null_hash_provider_impl : public hash_provider_impl + { + public: + bool is_enabled() const override + { + return false; + } + + void write(const uint8_t* data, size_t count) override + { + // no-op + UNREFERENCED_PARAMETER(data); + UNREFERENCED_PARAMETER(count); + } + + void close() override + { + // no-op + } + + utility::string_t hash() const override + { + return utility::string_t(); + } + }; + + class hash_provider + { + public: + hash_provider() + : m_implementation(std::make_shared()) + { + } + + bool is_enabled() const + { + return m_implementation->is_enabled(); + } + + void write(const uint8_t* data, size_t count) + { + m_implementation->write(data, count); + } + + void close() + { + m_implementation->close(); + } + + utility::string_t hash() const + { + return m_implementation->hash(); + } + + static hash_provider create_hmac_sha256_hash_provider(const std::vector& key) + { + return hash_provider(std::make_shared(key)); + } + + static hash_provider create_md5_hash_provider() + { + return hash_provider(std::make_shared()); + } + + private: + explicit hash_provider(std::shared_ptr implementation) + : m_implementation(implementation) + { + } + + // The hash provider implementation is in a separate object so the hash_provider object can be copied yet maintain the + // same shared state for the hashing progress, and so different implementations can store different state on the heap. + std::shared_ptr m_implementation; + }; + +}}} // namespace azure::storage::core diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/logging.h b/Microsoft.WindowsAzure.Storage/includes/wascore/logging.h index 2975e506..f0a82224 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/logging.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/logging.h @@ -34,7 +34,10 @@ namespace azure { namespace storage { namespace core { ~logger(); void log(azure::storage::operation_context context, client_log_level level, const std::string& message) const; + +#ifdef WIN32 void log(azure::storage::operation_context context, client_log_level level, const std::wstring& message) const; +#endif bool should_log(azure::storage::operation_context context, client_log_level level) const; private: diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h b/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h index 7ff7c1c5..2c80ee3e 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/protocol.h @@ -106,7 +106,7 @@ namespace azure { namespace storage { namespace protocol { // Common response parsers template - T preprocess_response(T return_value, const web::http::http_response& response, operation_context context) + T preprocess_response(T return_value, const web::http::http_response& response, const request_result&, operation_context) { switch (response.status_code()) { @@ -126,8 +126,7 @@ namespace azure { namespace storage { namespace protocol { return return_value; } - void preprocess_response(const web::http::http_response& response, operation_context context); - void check_stream_length_and_md5(utility::size64_t length, const utility::string_t& content_md5, const core::ostream_descriptor& descriptor); + void preprocess_response_void(const web::http::http_response& response, const request_result& result, operation_context context); utility::datetime parse_last_modified(const utility::string_t& value); utility::string_t parse_lease_id(const utility::string_t& value); diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/protocol_xml.h b/Microsoft.WindowsAzure.Storage/includes/wascore/protocol_xml.h index c16eb5a4..c6e24d58 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/protocol_xml.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/protocol_xml.h @@ -33,13 +33,13 @@ namespace azure { namespace storage { namespace protocol { { } - utility::string_t extract_error_code() + utility::string_t move_error_code() { parse(); return std::move(m_error_code); } - utility::string_t extract_error_message() + utility::string_t move_error_message() { parse(); return std::move(m_error_message); @@ -62,22 +62,22 @@ namespace azure { namespace storage { namespace protocol { { } - web::http::uri uri() + web::http::uri move_uri() { return std::move(m_uri); } - utility::string_t name() + utility::string_t move_name() { return std::move(m_name); } - cloud_metadata metadata() + cloud_metadata move_metadata() { return std::move(m_metadata); } - cloud_blob_container_properties properties() + cloud_blob_container_properties move_properties() { return std::move(m_properties); } @@ -99,13 +99,13 @@ namespace azure { namespace storage { namespace protocol { { } - std::vector extract_items() + std::vector move_items() { parse(); return std::move(m_items); } - utility::string_t extract_next_marker() + utility::string_t move_next_marker() { parse(); return std::move(m_next_marker); @@ -136,32 +136,32 @@ namespace azure { namespace storage { namespace protocol { { } - web::http::uri uri() + web::http::uri move_uri() { return std::move(m_uri); } - utility::string_t name() + utility::string_t move_name() { return std::move(m_name); } - utility::string_t snapshot_time() + utility::string_t move_snapshot_time() { return std::move(m_snapshot_time); } - cloud_metadata metadata() + cloud_metadata move_metadata() { return std::move(m_metadata); } - cloud_blob_properties properties() + cloud_blob_properties move_properties() { return std::move(m_properties); } - copy_state copy_state() + copy_state move_copy_state() { return std::move(m_copy_state); } @@ -185,12 +185,12 @@ namespace azure { namespace storage { namespace protocol { { } - web::http::uri uri() + web::http::uri move_uri() { return std::move(m_uri); } - utility::string_t name() + utility::string_t move_name() { return std::move(m_name); } @@ -210,19 +210,19 @@ namespace azure { namespace storage { namespace protocol { { } - std::vector extract_blob_items() + std::vector move_blob_items() { parse(); return std::move(m_blob_items); } - std::vector extract_blob_prefix_items() + std::vector move_blob_prefix_items() { parse(); return std::move(m_blob_prefix_items); } - utility::string_t extract_next_marker() + utility::string_t move_next_marker() { parse(); return std::move(m_next_marker); @@ -257,7 +257,7 @@ namespace azure { namespace storage { namespace protocol { } // Extracts the result. This method can only be called once on this reader - std::vector extract_result() + std::vector move_result() { parse(); return std::move(m_page_list); @@ -283,7 +283,7 @@ namespace azure { namespace storage { namespace protocol { } // Extracts the result. This method can only be called once on this reader - std::vector extract_result() + std::vector move_result() { parse(); return std::move(m_block_list); @@ -325,7 +325,7 @@ namespace azure { namespace storage { namespace protocol { { } - shared_access_policies extract_policies() + shared_access_policies move_policies() { parse(); return std::move(m_policies); @@ -427,12 +427,12 @@ namespace azure { namespace storage { namespace protocol { { } - utility::string_t name() + utility::string_t move_name() { return std::move(m_name); } - cloud_metadata metadata() + cloud_metadata move_metadata() { return std::move(m_metadata); } @@ -452,13 +452,13 @@ namespace azure { namespace storage { namespace protocol { { } - std::vector extract_items() + std::vector move_items() { parse(); return std::move(m_items); } - utility::string_t extract_next_marker() + utility::string_t move_next_marker() { parse(); return std::move(m_next_marker); @@ -466,7 +466,6 @@ namespace azure { namespace storage { namespace protocol { protected: - virtual void handle_begin_element(const utility::string_t& element_name); virtual void handle_element(const utility::string_t& element_name); virtual void handle_end_element(const utility::string_t& element_name); @@ -486,17 +485,17 @@ namespace azure { namespace storage { namespace protocol { { } - utility::string_t content() + utility::string_t move_content() { return std::move(m_content); } - utility::string_t id() + utility::string_t move_id() { return std::move(m_id); } - utility::string_t pop_receipt() + utility::string_t move_pop_receipt() { return std::move(m_pop_receipt); } @@ -537,11 +536,11 @@ namespace azure { namespace storage { namespace protocol { public: explicit message_reader(concurrency::streams::istream stream) - : xml_reader(stream) + : xml_reader(stream), m_dequeue_count(0) { } - std::vector extract_items() + std::vector move_items() { parse(); return std::move(m_items); @@ -549,7 +548,6 @@ namespace azure { namespace storage { namespace protocol { protected: - virtual void handle_begin_element(const utility::string_t& element_name); virtual void handle_element(const utility::string_t& element_name); virtual void handle_end_element(const utility::string_t& element_name); @@ -580,11 +578,11 @@ namespace azure { namespace storage { namespace protocol { public: explicit service_properties_reader(concurrency::streams::istream stream) - : xml_reader(stream), m_current_retention_policy_days(0) + : xml_reader(stream), m_current_retention_policy_days(0), m_current_retention_policy_enabled(false) { } - service_properties extract_properties() + service_properties move_properties() { parse(); return std::move(m_service_properties); @@ -634,7 +632,7 @@ namespace azure { namespace storage { namespace protocol { { } - service_stats extract_stats() + service_stats move_stats() { parse(); return std::move(m_service_stats); diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/streambuf.h b/Microsoft.WindowsAzure.Storage/includes/wascore/streambuf.h index 05d9657b..b3cb4796 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/streambuf.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/streambuf.h @@ -20,7 +20,7 @@ #include "cpprest/streams.h" #include "wascore/basic_types.h" -#include "resources.h" +#include "hashing.h" namespace azure { namespace storage { namespace core { @@ -28,6 +28,10 @@ namespace azure { namespace storage { namespace core { class basic_istreambuf : public concurrency::streams::details::streambuf_state_manager<_CharType> { public: + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::traits traits; + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::int_type int_type; + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::pos_type pos_type; + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::off_type off_type; basic_istreambuf() : concurrency::streams::details::streambuf_state_manager<_CharType>(std::ios_base::in) @@ -68,6 +72,10 @@ namespace azure { namespace storage { namespace core { class basic_ostreambuf : public concurrency::streams::details::streambuf_state_manager<_CharType> { public: + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::traits traits; + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::int_type int_type; + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::pos_type pos_type; + typedef typename concurrency::streams::details::streambuf_state_manager<_CharType>::off_type off_type; basic_ostreambuf() : concurrency::streams::details::streambuf_state_manager<_CharType>(std::ios_base::out) @@ -138,12 +146,17 @@ namespace azure { namespace storage { namespace core { }; template - class basic_splitter_streambuf : public basic_ostreambuf<_CharType> + class basic_hash_wrapper_streambuf : public basic_ostreambuf<_CharType> { public: + typedef _CharType char_type; + typedef typename basic_ostreambuf<_CharType>::traits traits; + typedef typename basic_ostreambuf<_CharType>::int_type int_type; + typedef typename basic_ostreambuf<_CharType>::pos_type pos_type; + typedef typename basic_ostreambuf<_CharType>::off_type off_type; - basic_splitter_streambuf(concurrency::streams::streambuf<_CharType> streambuf1, concurrency::streams::streambuf<_CharType> streambuf2) - : basic_ostreambuf<_CharType>(), m_streambuf1(streambuf1), m_streambuf2(streambuf2), m_total_written(0) + basic_hash_wrapper_streambuf(concurrency::streams::streambuf<_CharType> inner_streambuf, hash_provider provider) + : basic_ostreambuf<_CharType>(), m_inner_streambuf(inner_streambuf), m_hash_provider(provider), m_total_written(0) { } @@ -209,259 +222,51 @@ namespace azure { namespace storage { namespace core { pplx::task _sync() { - auto streambuf2 = m_streambuf2; - return m_streambuf1.sync().then([streambuf2] () mutable -> pplx::task + return m_inner_streambuf.sync().then([]() -> bool { - return streambuf2.sync().then([] () -> bool - { - return true; - }); + return true; }); } pplx::task _close_write() { - basic_ostreambuf<_CharType>::_close_write(); - auto streambuf2 = m_streambuf2; - return m_streambuf1.close(std::ios_base::out).then([streambuf2] () mutable -> pplx::task - { - return streambuf2.close(std::ios_base::out); - }); + m_hash_provider.close(); + return m_inner_streambuf.close(std::ios_base::out); } pplx::task _putc(char_type ch) { - m_total_written++; - auto streambuf2 = m_streambuf2; - return m_streambuf1.putc(ch).then([streambuf2, ch] (int_type result1) mutable -> pplx::task - { - return streambuf2.putc(ch).then([result1] (int_type result2) -> int_type - { - if (result1 != result2) - { - throw; - } - - return result1; - }); - }); - } - - pplx::task _putn(const char_type* ptr, size_t count) - { - m_total_written += count; - auto streambuf2 = m_streambuf2; - return m_streambuf1.putn(ptr, count).then([streambuf2, ptr, count] (size_t result1) mutable -> pplx::task - { - return streambuf2.putn(ptr, count).then([result1] (size_t result2) -> size_t - { - if (result1 != result2) - { - throw; - } - - return result1; - }); - }); - } - - utility::size64_t total_written() const - { - return m_total_written; - } - - private: - - concurrency::streams::streambuf<_CharType> m_streambuf1; - concurrency::streams::streambuf<_CharType> m_streambuf2; - utility::size64_t m_total_written; - }; - - template - class basic_null_streambuf : public basic_ostreambuf<_CharType> - { - public: - - basic_null_streambuf() - : basic_ostreambuf<_CharType>() - { - } - - bool can_seek() const - { - return false; - } - - bool has_size() const - { - return false; - } - - utility::size64_t size() const - { - return (utility::size64_t)0; - } - - size_t buffer_size(std::ios_base::openmode direction) const - { - UNREFERENCED_PARAMETER(direction); - return (size_t)0; - } - - void set_buffer_size(size_t size, std::ios_base::openmode direction) - { - UNREFERENCED_PARAMETER(size); - UNREFERENCED_PARAMETER(direction); - } - - pos_type getpos(std::ios_base::openmode direction) const - { - UNREFERENCED_PARAMETER(direction); - return (pos_type)traits::eof(); - } - - pos_type seekoff(off_type offset, std::ios_base::seekdir way, std::ios_base::openmode direction) - { - UNREFERENCED_PARAMETER(offset); - UNREFERENCED_PARAMETER(way); - UNREFERENCED_PARAMETER(direction); - return (pos_type)traits::eof(); - } - - pos_type seekpos(pos_type pos, std::ios_base::openmode direction) - { - UNREFERENCED_PARAMETER(pos); - UNREFERENCED_PARAMETER(direction); - return (pos_type)traits::eof(); - } - - char_type* _alloc(_In_ size_t count) - { - UNREFERENCED_PARAMETER(count); - return nullptr; - } - - void _commit(_In_ size_t count) - { - UNREFERENCED_PARAMETER(count); - // no-op, as hash streams do not support alloc/commit - } - - pplx::task _sync() - { - return pplx::task_from_result(true); - } + // TODO: Consider updating the length and MD5 hash only after writing the data in case writing fails (in a task continuation) + ++m_total_written; + m_hash_provider.write(&ch, 1); - pplx::task _close_write() - { - return basic_ostreambuf<_CharType>::_close_write(); - } - - pplx::task _putc(char_type ch) - { - return pplx::task_from_result((int_type)ch); + return m_inner_streambuf.putc(ch); } pplx::task _putn(const char_type* ptr, size_t count) { - UNREFERENCED_PARAMETER(ptr); - return pplx::task_from_result(count); - } - }; - - class basic_hash_streambuf : public basic_ostreambuf - { - public: - - basic_hash_streambuf() - : basic_ostreambuf() - { - } - - bool can_seek() const - { - return false; - } - - bool has_size() const - { - return false; - } - - utility::size64_t size() const - { - return (utility::size64_t)0; - } - - size_t buffer_size(std::ios_base::openmode direction) const - { - UNREFERENCED_PARAMETER(direction); - return (size_t)0; - } - - void set_buffer_size(size_t size, std::ios_base::openmode direction) - { - UNREFERENCED_PARAMETER(size); - UNREFERENCED_PARAMETER(direction); - } - - pos_type getpos(std::ios_base::openmode direction) const - { - UNREFERENCED_PARAMETER(direction); - return (pos_type)traits::eof(); - } - - pos_type seekoff(off_type offset, std::ios_base::seekdir way, std::ios_base::openmode direction) - { - UNREFERENCED_PARAMETER(offset); - UNREFERENCED_PARAMETER(way); - UNREFERENCED_PARAMETER(direction); - return (pos_type)traits::eof(); - } - - pos_type seekpos(pos_type pos, std::ios_base::openmode direction) - { - UNREFERENCED_PARAMETER(pos); - UNREFERENCED_PARAMETER(direction); - return (pos_type)traits::eof(); - } + // TODO: Consider updating the length and MD5 hash only after writing the data in case writing fails (in a task continuation) + m_total_written += count; + m_hash_provider.write(ptr, count); - char_type* _alloc(_In_ size_t count) - { - UNREFERENCED_PARAMETER(count); - return nullptr; + return m_inner_streambuf.putn(ptr, count); } - void _commit(_In_ size_t count) + utility::string_t hash() const { - UNREFERENCED_PARAMETER(count); - // no-op, as hash streams do not support alloc/commit + return m_hash_provider.hash(); } - pplx::task _sync() - { - return pplx::task_from_result(true); - } - - const std::vector& hash() const + utility::size64_t total_written() const { - if (is_open()) - { - throw std::logic_error(protocol::error_hash_on_closed_streambuf); - } - - return m_hash; + return m_total_written; } - protected: + private: - void store_and_throw(std::exception_ptr e) - { - m_currentException = e; - std::rethrow_exception(e); - } - - std::vector m_hash; + concurrency::streams::streambuf<_CharType> m_inner_streambuf; + hash_provider m_hash_provider; + utility::size64_t m_total_written; }; }}} // namespace azure::storage::core diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/streams.h b/Microsoft.WindowsAzure.Storage/includes/wascore/streams.h index 351d1698..c3b8b50a 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/streams.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/streams.h @@ -20,85 +20,33 @@ #include "wascore/basic_types.h" #include "streambuf.h" -#ifdef WIN32 -#include "hash_windows.h" -#else -#include "hash_linux.h" -#endif - namespace azure { namespace storage { namespace core { template - class splitter_streambuf : public concurrency::streams::streambuf<_CharType> + class hash_wrapper_streambuf : public concurrency::streams::streambuf<_CharType> { public: - splitter_streambuf() + hash_wrapper_streambuf() : concurrency::streams::streambuf<_CharType>() { } - splitter_streambuf(concurrency::streams::streambuf<_CharType> streambuf1, concurrency::streams::streambuf<_CharType> streambuf2) - : concurrency::streams::streambuf<_CharType>(std::make_shared>(streambuf1, streambuf2)) + hash_wrapper_streambuf(concurrency::streams::streambuf<_CharType> inner_streambuf, hash_provider provider) + : concurrency::streams::streambuf<_CharType>(std::make_shared>(inner_streambuf, provider)) { } utility::size64_t total_written() const { - auto base = static_cast*>(get_base().get()); + const basic_hash_wrapper_streambuf<_CharType>* base = static_cast*>(Concurrency::streams::streambuf<_CharType>::get_base().get()); return base->total_written(); } - }; - template - class null_streambuf : public concurrency::streams::streambuf<_CharType> - { - public: - - null_streambuf() - : concurrency::streams::streambuf<_CharType>(std::make_shared>()) + utility::string_t hash() const { - } - }; - - class hash_streambuf : public concurrency::streams::streambuf - { - public: - - hash_streambuf() - : concurrency::streams::streambuf() - { - } - - explicit hash_streambuf(const std::shared_ptr &ptr) - : concurrency::streams::streambuf(ptr) - { - } - - const std::vector& hash() const - { - auto base = static_cast(get_base().get()); + const basic_hash_wrapper_streambuf<_CharType>* base = static_cast*>(Concurrency::streams::streambuf<_CharType>::get_base().get()); return base->hash(); } }; - class hash_hmac_sha256_streambuf : public hash_streambuf - { - public: - - explicit hash_hmac_sha256_streambuf(std::vector key) - : hash_streambuf(std::make_shared(std::move(key))) - { - } - }; - - class hash_md5_streambuf : public hash_streambuf - { - public: - - hash_md5_streambuf() - : hash_streambuf(std::make_shared()) - { - } - }; - }}} // namespace azure::storage::core diff --git a/Microsoft.WindowsAzure.Storage/includes/wascore/xmlhelpers.h b/Microsoft.WindowsAzure.Storage/includes/wascore/xmlhelpers.h index 10accbc4..aad0fe7a 100644 --- a/Microsoft.WindowsAzure.Storage/includes/wascore/xmlhelpers.h +++ b/Microsoft.WindowsAzure.Storage/includes/wascore/xmlhelpers.h @@ -54,6 +54,7 @@ #include #include "cpprest/basic_types.h" +#include "was/core.h" namespace azure { namespace storage { namespace core { namespace xml { diff --git a/Microsoft.WindowsAzure.Storage/packages.config b/Microsoft.WindowsAzure.Storage/packages.config index a7574f84..9e4930c4 100644 --- a/Microsoft.WindowsAzure.Storage/packages.config +++ b/Microsoft.WindowsAzure.Storage/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp index 15560df0..92b0dd59 100644 --- a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Application.cpp @@ -40,7 +40,9 @@ namespace azure { namespace storage { namespace samples { // Create a blob container azure::storage::cloud_blob_client blob_client = storage_account.create_cloud_blob_client(); azure::storage::cloud_blob_container container = blob_client.get_container_reference(U("my-sample-container")); - bool created = container.create_if_not_exists(); + + // Return value is true if the container did not exist and was successfully created. + container.create_if_not_exists(); // Make the blob container publicly accessible azure::storage::blob_container_permissions permissions; @@ -96,7 +98,8 @@ namespace azure { namespace storage { namespace samples { blob3.delete_blob(); // Delete the blob container - bool deleted = container.delete_container_if_exists(); + // Return value is true if the container did exist and was successfully deleted. + container.delete_container_if_exists(); } catch (const azure::storage::storage_exception& e) { @@ -117,7 +120,7 @@ namespace azure { namespace storage { namespace samples { }}} // namespace azure::storage::samples -int _tmain(int argc, _TCHAR *argv[]) +int main(int argc, const char *argv[]) { azure::storage::samples::blobs_getting_started_sample(); return 0; diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/CMakeLists.txt new file mode 100644 index 00000000..6b8f6b1f --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/CMakeLists.txt @@ -0,0 +1,57 @@ +include_directories(../../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS}) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + Application.cpp + stdafx.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + Application.cpp + stdafx.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_executable(${AZURESTORAGESAMPLES_BLOBS} ${SOURCES}) + +target_link_libraries(${AZURESTORAGESAMPLES_BLOBS} + ${AZURESTORAGESAMPLES_COMMON} + ${AZURE_STORAGE_LIBRARY} + ${UUID_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +if(WIN32) + set_target_properties(${AZURESTORAGESAMPLES_BLOBS} PROPERTIES + OUTPUT_NAME "${AZURESTORAGESAMPLES_BLOBS}") +else() + set_target_properties(${AZURESTORAGESAMPLES_BLOBS} PROPERTIES + SOVERSION ${AZURESTORAGE_VERSION_MAJOR}.${AZURESTORAGE_VERSION_MINOR}) +endif() + 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 5da77117..8d618a22 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 @@ -1,6 +1,7 @@  - + + Debug @@ -115,6 +116,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.vcxproj b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.vcxproj index fabd34c2..e7021fe1 100644 --- a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/Microsoft.WindowsAzure.Storage.BlobsGettingStarted.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -115,6 +116,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/packages.config b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/packages.config index a7574f84..9e4930c4 100644 --- a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/packages.config +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/stdafx.h b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/stdafx.h index 8ee7a2c9..e52a6520 100644 --- a/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/stdafx.h +++ b/Microsoft.WindowsAzure.Storage/samples/BlobsGettingStarted/stdafx.h @@ -24,7 +24,5 @@ #include "targetver.h" -#include - #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers diff --git a/Microsoft.WindowsAzure.Storage/samples/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/samples/CMakeLists.txt new file mode 100644 index 00000000..f63ad50a --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/samples/CMakeLists.txt @@ -0,0 +1,110 @@ +set(CMAKE_LEGACY_CYGWIN_WIN32 0) +cmake_minimum_required(VERSION 2.6) +project(azurestoragesamples) + +enable_testing() + +set(WARNINGS) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../cmake/Modules/") + +# Platform (not compiler) specific settings +if(IOS) + set(IOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../../Build_iOS") + set(Boost_FRAMEWORK "-F ${IOS_SOURCE_DIR} -framework boost") + set(Boost_INCLUDE_DIR "${IOS_SOURCE_DIR}/boost.framework/Headers") + + set(OPENSSL_FOUND 1) + set(OPENSSL_INCLUDE_DIR "${IOS_SOURCE_DIR}/openssl/include") + set(OPENSSL_LIBRARIES + "${IOS_SOURCE_DIR}/openssl/lib/libcrypto.a" + "${IOS_SOURCE_DIR}/openssl/lib/libssl.a" + ) + + set(CASABLANCA_INCLUDE_DIR "${IOS_SOURCE_DIR}/casablanca/include") + set(CASABLANCA_LIBRARY "${IOS_SOURCE_DIR}/casablanca/lib/libcasablanca.a") + + # The cxx_flags must be set here, because the ios-cmake toolchain file unfortunately sets "-headerpad_max_install_names" which is not a valid clang flag. + set(CMAKE_CXX_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden") + + set(BUILD_SHARED_LIBS OFF) +elseif(UNIX) # This includes OSX + find_package(Boost REQUIRED COMPONENTS log log_setup random system thread locale regex filesystem) + find_package(Threads REQUIRED) + find_package(OpenSSL REQUIRED) + find_package(LibXML++ REQUIRED) + find_package(UUID REQUIRED) + find_package(Casablanca REQUIRED) + + set(AZURE_STORAGE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/..") + set(AZURE_STORAGE_INCLUDE_DIR "${AZURE_STORAGE_SOURCE_DIR}/includes") + set(AZURE_STORAGE_LIBRARY "${AZURE_STORAGE_SOURCE_DIR}/build.release/Binaries/libazurestorage.so") + + option(BUILD_SHARED_LIBS "Build shared Libraries." ON) +elseif(WIN32) + option(BUILD_SHARED_LIBS "Build shared Libraries." ON) + + add_definitions(-DUNICODE) + + if(NOT BUILD_SHARED_LIBS) + # This causes cmake to not link the test libraries separately, but instead hold onto their object files. + set(TEST_LIBRARY_TARGET_TYPE OBJECT) + endif() + + set(LIB lib) +else() + message("-- Unsupported Build Platform.") +endif() + +# Compiler (not platform) specific settings +if(("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR IOS) + message("-- Setting clang options") + + set(WARNINGS "-Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls") + set(OSX_SUPPRESSIONS "-Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder") + set(WARNINGS "${WARNINGS} ${OSX_SUPPRESSIONS}") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") + set(STRICT_CXX_FLAGS ${WARNINGS} "-Werror -pedantic") +elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") + message("-- Setting gcc options") + + set(WARNINGS "-Wall -Wextra -Wunused-parameter -Wcast-align -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls -Wunreachable-code") + set(LINUX_SUPPRESSIONS "-Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-unused-function -Wno-char-subscripts -Wno-switch -Wno-unused-but-set-parameter -Wno-unused-value -Wno-unused-local-typedefs -Wno-unused-parameter") + + set(WARNINGS "${WARNINGS} ${LINUX_SUPPRESSIONS}") + set(LD_FLAGS "${LD_FLAGS} -Wl,-z,defs") + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-strict-aliasing") + set(STRICT_CXX_FLAGS ${WARNINGS} "-Werror -pedantic") + add_definitions(-DBOOST_LOG_DYN_LINK) +else() + message("-- Unknown compiler, success is doubtful.") +endif() + +# Reconfigure final output directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) + +set(AZURESTORAGESAMPLES_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/SamplesCommon) +set(AZURESTORAGESAMPLES_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/SamplesCommon ${AZURE_STORAGE_INCLUDE_DIR} ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS} ${UUID_INCLUDE_DIRS}) + +set(AZURESTORAGESAMPLES_COMMON samplescommon) +set(AZURESTORAGESAMPLES_BLOBS samplesblobs) +set(AZURESTORAGESAMPLES_JSON samplesjson) +set(AZURESTORAGESAMPLES_TABLES samplestables) +set(AZURESTORAGESAMPLES_QUEUES samplesqueues) +set(AZURESTORAGESAMPLES_LIBRARIES ${AZURESTORAGESAMPLES_COMMON} ${AZURESTORAGE_LIBRARY} ${CASABLANCA_LIBRARY} ${Boost_LIBRARIES} ${Boost_FRAMEWORK} ${OPENSSL_LIBRARIES} ${LibXML++_LIBRARIES} ${UUID_LIBRARIES}) + +include_directories(${AZURESTORAGESAMPLES_INCLUDE_DIRS}) + +add_subdirectory(SamplesCommon) +add_subdirectory(BlobsGettingStarted) +add_subdirectory(JsonPayloadFormat) +add_subdirectory(QueuesGettingStarted) +add_subdirectory(TablesGettingStarted) diff --git a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Application.cpp b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Application.cpp index a89db644..1a978c77 100644 --- a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Application.cpp +++ b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Application.cpp @@ -33,7 +33,9 @@ namespace azure { namespace storage { namespace samples { // Create a table azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client(); azure::storage::cloud_table table = table_client.get_table_reference(U("MySampleTable")); - bool created = table.create_if_not_exists(); + + // Return value is true if the table did not exist and was successfully created. + table.create_if_not_exists(); // Insert some table entities azure::storage::table_batch_operation batch_operation; @@ -47,7 +49,7 @@ namespace azure { namespace storage { namespace samples { properties[U("DateTimeProperty")] = azure::storage::entity_property(utility::datetime::utc_now()); properties[U("GuidProperty")] = azure::storage::entity_property(utility::new_uuid()); properties[U("Int32Property")] = azure::storage::entity_property(1234567890); - properties[U("Int64Property")] = azure::storage::entity_property(1234567890123456789LL); + properties[U("Int64Property")] = azure::storage::entity_property((int64_t) 1234567890123456789LL); properties[U("DoubleProperty")] = azure::storage::entity_property(9.1234567890123456789); properties[U("BooleanProperty")] = azure::storage::entity_property(true); properties[U("BinaryProperty")] = azure::storage::entity_property(std::vector(10, 'X')); @@ -87,7 +89,8 @@ namespace azure { namespace storage { namespace samples { } // Delete the table - bool deleted = table.delete_table_if_exists(); + // Return value is true if the table did exist and was successfully deleted. + table.delete_table_if_exists(); } catch (const azure::storage::storage_exception& e) { @@ -108,7 +111,7 @@ namespace azure { namespace storage { namespace samples { }}} // namespace azure::storage::samples -int _tmain(int argc, _TCHAR *argv[]) +int main(int argc, const char *argv[]) { azure::storage::samples::tables_getting_started_sample(); return 0; diff --git a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/CMakeLists.txt new file mode 100644 index 00000000..0bd64a3f --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/CMakeLists.txt @@ -0,0 +1,57 @@ +include_directories(../../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS}) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + Application.cpp + stdafx.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + Application.cpp + stdafx.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_executable(${AZURESTORAGESAMPLES_JSON} ${SOURCES}) + +target_link_libraries(${AZURESTORAGESAMPLES_JSON} + ${AZURESTORAGESAMPLES_COMMON} + ${AZURE_STORAGE_LIBRARY} + ${UUID_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +if(WIN32) + set_target_properties(${AZURESTORAGESAMPLES_JSON} PROPERTIES + OUTPUT_NAME "${AZURESTORAGESAMPLES_JSON}") +else() + set_target_properties(${AZURESTORAGESAMPLES_JSON} PROPERTIES + SOVERSION ${AZURESTORAGE_VERSION_MAJOR}.${AZURESTORAGE_VERSION_MINOR}) +endif() + 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 5007e730..935a6bbd 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 @@ -1,6 +1,7 @@  - + + Debug @@ -110,6 +111,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.vcxproj b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.vcxproj index bcd4069b..3c2c1b2d 100644 --- a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/Microsoft.WindowsAzure.Storage.JsonPayloadFormat.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -110,6 +111,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/packages.config b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/packages.config index a7574f84..9e4930c4 100644 --- a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/packages.config +++ b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/stdafx.h b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/stdafx.h index 8ee7a2c9..e52a6520 100644 --- a/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/stdafx.h +++ b/Microsoft.WindowsAzure.Storage/samples/JsonPayloadFormat/stdafx.h @@ -24,7 +24,5 @@ #include "targetver.h" -#include - #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers diff --git a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Application.cpp b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Application.cpp index e4d954c8..4e2cdbe1 100644 --- a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Application.cpp +++ b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Application.cpp @@ -33,7 +33,9 @@ namespace azure { namespace storage { namespace samples { // Create a queue azure::storage::cloud_queue_client queue_client = storage_account.create_cloud_queue_client(); azure::storage::cloud_queue queue = queue_client.get_queue_reference(U("my-sample-queue")); - bool created = queue.create_if_not_exists(); + + // Return value is true if the queue did not exist and was successfully created. + queue.create_if_not_exists(); // Insert some queue messages azure::storage::cloud_queue_message message1(U("some message")); @@ -76,10 +78,11 @@ namespace azure { namespace storage { namespace samples { // Get the approximate queue size queue.download_attributes(); - int message_count = queue.approximate_message_count(); + ucout << U("Approximate message count: ") << queue.approximate_message_count() << std::endl; // Delete the queue - bool deleted = queue.delete_queue_if_exists(); + // Return value is true if the queue did exist and was succesfully deleted. + queue.delete_queue_if_exists(); } catch (const azure::storage::storage_exception& e) { @@ -100,7 +103,7 @@ namespace azure { namespace storage { namespace samples { }}} // namespace azure::storage::samples -int _tmain(int argc, _TCHAR *argv[]) +int main(int argc, const char *argv[]) { azure::storage::samples::queues_getting_started_sample(); return 0; diff --git a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/CMakeLists.txt new file mode 100644 index 00000000..5be9734f --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/CMakeLists.txt @@ -0,0 +1,57 @@ +include_directories(../../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS}) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + Application.cpp + stdafx.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + Application.cpp + stdafx.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_executable(${AZURESTORAGESAMPLES_QUEUES} ${SOURCES}) + +target_link_libraries(${AZURESTORAGESAMPLES_QUEUES} + ${AZURESTORAGESAMPLES_COMMON} + ${AZURE_STORAGE_LIBRARY} + ${UUID_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +if(WIN32) + set_target_properties(${AZURESTORAGESAMPLES_QUEUES} PROPERTIES + OUTPUT_NAME "${AZURESTORAGESAMPLES_QUEUES}") +else() + set_target_properties(${AZURESTORAGESAMPLES_QUEUES} PROPERTIES + SOVERSION ${AZURESTORAGE_VERSION_MAJOR}.${AZURESTORAGE_VERSION_MINOR}) +endif() + 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 d5d7718f..66201b26 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 @@ -1,6 +1,7 @@  - + + Debug @@ -110,6 +111,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.vcxproj b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.vcxproj index d305e8c5..9faff45a 100644 --- a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/Microsoft.WindowsAzure.Storage.QueuesGettingStarted.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -110,6 +111,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/packages.config b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/packages.config index a7574f84..9e4930c4 100644 --- a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/packages.config +++ b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/stdafx.h b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/stdafx.h index 8ee7a2c9..e52a6520 100644 --- a/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/stdafx.h +++ b/Microsoft.WindowsAzure.Storage/samples/QueuesGettingStarted/stdafx.h @@ -24,7 +24,5 @@ #include "targetver.h" -#include - #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers diff --git a/Microsoft.WindowsAzure.Storage/samples/SamplesCommon/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/samples/SamplesCommon/CMakeLists.txt new file mode 100644 index 00000000..143ef44b --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/samples/SamplesCommon/CMakeLists.txt @@ -0,0 +1,56 @@ +include_directories(../../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS}) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + stdafx.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + stdafx.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_library(${AZURESTORAGESAMPLES_COMMON} ${SOURCES}) + +target_link_libraries(${AZURESTORAGESAMPLES_COMMON} + ${AZURE_STORAGE_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +set (AZURESTORAGESAMPLES_VERSION_MAJOR 0) +set (AZURESTORAGESAMPLES_VERSION_MINOR 4) +set (AZURESTORAGESAMPLES_VERSION_REVISION 0) +if(WIN32) + set_target_properties(${AZURESTORAGESAMPLES_COMMON} PROPERTIES + OUTPUT_NAME "${AZURESTORAGESAMPLES_COMMON}_${AZURESTORAGESAMPLES_VERSION_MAJOR}_${AZURESTORAGESAMPLES_VERSION_MINOR}") +else() + set_target_properties(${AZURESTORAGESAMPLES_COMMON} PROPERTIES + SOVERSION ${AZURESTORAGESAMPLES_VERSION_MAJOR}.${AZURESTORAGESAMPLES_VERSION_MINOR}) +endif() + diff --git a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Application.cpp b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Application.cpp index 8e649fc8..25e44d57 100644 --- a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Application.cpp +++ b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Application.cpp @@ -33,7 +33,9 @@ namespace azure { namespace storage { namespace samples { // Create a table azure::storage::cloud_table_client table_client = storage_account.create_cloud_table_client(); azure::storage::cloud_table table = table_client.get_table_reference(U("MySampleTable")); - bool created = table.create_if_not_exists(); + + // Return value is true if the table did not exist and was successfully created. + table.create_if_not_exists(); // Insert a table entity azure::storage::table_entity entity(U("MyPartitionKey"), U("MyRowKey")); @@ -43,7 +45,7 @@ namespace azure { namespace storage { namespace samples { properties[U("DateTimeProperty")] = azure::storage::entity_property(utility::datetime::utc_now()); properties[U("GuidProperty")] = azure::storage::entity_property(utility::new_uuid()); properties[U("Int32Property")] = azure::storage::entity_property(1234567890); - properties[U("Int64Property")] = azure::storage::entity_property(1234567890123456789LL); + properties[U("Int64Property")] = azure::storage::entity_property((int64_t) 1234567890123456789LL); properties[U("DoubleProperty")] = azure::storage::entity_property(9.1234567890123456789); properties[U("BooleanProperty")] = azure::storage::entity_property(true); properties[U("BinaryProperty")] = azure::storage::entity_property(std::vector(10, 'X')); @@ -75,7 +77,7 @@ namespace azure { namespace storage { namespace samples { azure::storage::table_query query; query.set_filter_string(azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::generate_filter_condition(U("PartitionKey"), azure::storage::query_comparison_operator::equal, U("MyPartitionKey")), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::greater_than_or_equal, U("MyRowKey5")))); std::vector entities = table.execute_query(query); for (std::vector::const_iterator it = entities.cbegin(); it != entities.cend(); ++it) @@ -89,7 +91,8 @@ namespace azure { namespace storage { namespace samples { azure::storage::table_result delete_result = table.execute(delete_operation); // Delete the table - bool deleted = table.delete_table_if_exists(); + // Return value is true if the table did exist and was successfully deleted. + table.delete_table_if_exists(); } catch (const azure::storage::storage_exception& e) { @@ -110,7 +113,7 @@ namespace azure { namespace storage { namespace samples { }}} // namespace azure::storage::samples -int _tmain(int argc, _TCHAR *argv[]) +int main(int argc, const char *argv[]) { azure::storage::samples::tables_getting_started_sample(); return 0; diff --git a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/CMakeLists.txt new file mode 100644 index 00000000..cf71b96d --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/CMakeLists.txt @@ -0,0 +1,57 @@ +include_directories(../../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS}) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + Application.cpp + stdafx.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + Application.cpp + stdafx.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_executable(${AZURESTORAGESAMPLES_TABLES} ${SOURCES}) + +target_link_libraries(${AZURESTORAGESAMPLES_TABLES} + ${AZURESTORAGESAMPLES_COMMON} + ${AZURE_STORAGE_LIBRARY} + ${UUID_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +if(WIN32) + set_target_properties(${AZURESTORAGESAMPLES_TABLES} PROPERTIES + OUTPUT_NAME "${AZURESTORAGESAMPLES_TABLES}") +else() + set_target_properties(${AZURESTORAGESAMPLES_TABLES} PROPERTIES + SOVERSION ${AZURESTORAGE_VERSION_MAJOR}.${AZURESTORAGE_VERSION_MINOR}) +endif() + 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 62e2d068..a0d2011e 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 @@ -1,6 +1,7 @@  - + + Debug @@ -110,6 +111,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.vcxproj b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.vcxproj index 55b56a53..6cbed763 100644 --- a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.vcxproj +++ b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/Microsoft.WindowsAzure.Storage.TablesGettingStarted.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -110,6 +111,10 @@ - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/packages.config b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/packages.config index a7574f84..9e4930c4 100644 --- a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/packages.config +++ b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/stdafx.h b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/stdafx.h index 8ee7a2c9..e52a6520 100644 --- a/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/stdafx.h +++ b/Microsoft.WindowsAzure.Storage/samples/TablesGettingStarted/stdafx.h @@ -24,7 +24,5 @@ #include "targetver.h" -#include - #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers diff --git a/Microsoft.WindowsAzure.Storage/src/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/src/CMakeLists.txt new file mode 100644 index 00000000..00feb409 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/src/CMakeLists.txt @@ -0,0 +1,135 @@ +include_directories(../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS}) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + xmlhelpers.cpp + response_parsers.cpp + request_result.cpp + request_factory.cpp + protocol_xml.cpp + navigation.cpp + async_semaphore.cpp + util.cpp + table_request_factory.cpp + table_response_parsers.cpp + table_query.cpp + entity_property.cpp + shared_access_signature.cpp + retry_policies.cpp + queue_request_factory.cpp + protocol_json.cpp + operation_context.cpp + mime_multipart_helper.cpp + logging.cpp + hashing.cpp + cloud_table_client.cpp + cloud_table.cpp + cloud_storage_account.cpp + cloud_queue_message.cpp + cloud_queue_client.cpp + cloud_queue.cpp + cloud_page_blob.cpp + cloud_core.cpp + cloud_client.cpp + cloud_block_blob.cpp + cloud_blob_directory.cpp + cloud_blob_container.cpp + cloud_blob_shared.cpp + cloud_blob_ostreambuf.cpp + cloud_blob_istreambuf.cpp + cloud_blob_client.cpp + cloud_blob.cpp + blob_response_parsers.cpp + blob_request_factory.cpp + basic_types.cpp + authentication.cpp + cloud_common.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + xmlhelpers.cpp + response_parsers.cpp + request_result.cpp + request_factory.cpp + protocol_xml.cpp + navigation.cpp + async_semaphore.cpp + util.cpp + table_request_factory.cpp + table_response_parsers.cpp + table_query.cpp + entity_property.cpp + shared_access_signature.cpp + retry_policies.cpp + queue_request_factory.cpp + protocol_json.cpp + operation_context.cpp + mime_multipart_helper.cpp + cloud_table_client.cpp + cloud_table.cpp + cloud_storage_account.cpp + cloud_queue_message.cpp + cloud_queue_client.cpp + cloud_queue.cpp + cloud_page_blob.cpp + cloud_core.cpp + cloud_client.cpp + cloud_block_blob.cpp + cloud_blob_directory.cpp + cloud_blob_container.cpp + cloud_blob_shared.cpp + cloud_blob_ostreambuf.cpp + cloud_blob_istreambuf.cpp + cloud_blob_client.cpp + cloud_blob.cpp + blob_response_parsers.cpp + blob_request_factory.cpp + basic_types.cpp + authentication.cpp + cloud_common.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_library(${AZURESTORAGE_LIBRARY} ${SOURCES}) + +target_link_libraries(${AZURESTORAGE_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +set (AZURESTORAGE_VERSION_MAJOR 0) +set (AZURESTORAGE_VERSION_MINOR 4) +set (AZURESTORAGE_VERSION_REVISION 0) +if(WIN32) + set_target_properties(${AZURESTORAGE_LIBRARY} PROPERTIES + OUTPUT_NAME "${AZURESTORAGE_LIBRARY}_${AZURESTORAGE_VERSION_MAJOR}_${AZURESTORAGE_VERSION_MINOR}") +else() + set_target_properties(${AZURESTORAGE_LIBRARY} PROPERTIES + SOVERSION ${AZURESTORAGE_VERSION_MAJOR}.${AZURESTORAGE_VERSION_MINOR}) +endif() + diff --git a/Microsoft.WindowsAzure.Storage/src/Makefile b/Microsoft.WindowsAzure.Storage/src/Makefile new file mode 100644 index 00000000..481f1504 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/src/Makefile @@ -0,0 +1,146 @@ +LIBRARY=azurestorage.so + +SOURCES = \ + xmlhelpers.cpp \ + util_windows.cpp \ + response_parsers.cpp \ + request_result.cpp \ + request_factory.cpp \ + protocol_xml.cpp \ + navigation.cpp \ + async_semaphore.cpp \ + util.cpp \ + table_request_factory.cpp \ + table_response_parsers.cpp \ + table_query.cpp \ + entity_property.cpp \ + shared_access_signature.cpp \ + retry_policies.cpp \ + queue_request_factory.cpp \ + protocol_json.cpp \ + operation_context.cpp \ + mime_multipart_helper.cpp \ + logging_windows.cpp \ + hash_windows.cpp \ + cloud_table_client.cpp \ + cloud_table.cpp \ + cloud_storage_account.cpp \ + cloud_queue_message.cpp \ + cloud_queue_client.cpp \ + cloud_queue.cpp \ + cloud_page_blob.cpp \ + cloud_core.cpp \ + cloud_client.cpp \ + cloud_block_blob.cpp \ + cloud_blob_directory.cpp \ + cloud_blob_container.cpp \ + cloud_blob_shared.cpp \ + cloud_blob_ostreambuf.cpp \ + cloud_blob_istreambuf.cpp \ + cloud_blob_client.cpp \ + cloud_blob.cpp \ + blob_response_parsers.cpp \ + blob_request_factory.cpp \ + basic_types.cpp \ + authentication.cpp \ + cloud_common.cpp + +ifeq ($(UNAME),APPLE) + # SOURCES += apple.cpp +else + # SOURCES += linux.cpp +endif + + +HEADERS = \ + ../includes/wascore/async_semaphore.h \ + ../includes/wascore/basic_types.h \ + ../includes/wascore/blobstreams.h \ + ../includes/wascore/constants.h \ + ../includes/wascore/executor.h \ + ../includes/wascore/hash_linux.h \ + ../includes/wascore/logging.h \ + ../includes/wascore/protocol_json.h \ + ../includes/wascore/protocol_xml.h \ + ../includes/wascore/protocol.h \ + ../includes/wascore/resources.h \ + ../includes/wascore/streambuf.h \ + ../includes/wascore/streams.h \ + ../includes/wascore/util.h \ + ../includes/wascore/xmlhelpers.h \ + ../includes/wascore/xmlstream.h \ + ../includes/was/auth.h \ + ../includes/was/blob.h \ + ../includes/was/common.h \ + ../includes/was/core.h \ + ../includes/was/queue.h \ + ../includes/was/retry_policies.h \ + ../includes/was/service_client.h \ + ../includes/was/storage_account.h \ + ../includes/was/table.h \ + ../includes/targetver.h \ + ../includes/stdafx.h + +ifeq ($(UNAME),APPLE) + # HEADERS += ../include/compat/apple_compat.h +else + # HEADERS += ../include/compat/linux_compat.h +endif + +PCH = ../includes/stdafx.h + +PRECOMPILED_HEADERS = $(addsuffix .gch, $(PCH)) +OBJECTS = $(addsuffix .$(MODE).o, $(basename $(SOURCES))) +CPP_DEPENDENCIES = $(addsuffix .d, $(basename $(SOURCES))) + +# flags for the C++ compiler + +ifeq ($(UNAME),LINUX) +PKGCONFIG_CFLAGS = $(shell pkg-config libxml++-2.6 --cflags) +PKGCONFIG_LIBS = $(shell pkg-config libxml++-2.6 --libs) $(shell pkg-config libssl --libs) +endif + +ifeq ($(UNAME),APPLE) +PLATFORM_FLAGS = -framework CoreFoundation +endif +ifeq ($(UNAME),LINUX) +PLATFORM_FLAGS = -pthread +endif + +#-fpch-deps -MMD not useful with a single monolithic PCH + +CXXFLAGS = -fPIC -std=c++11 $(STRICT_BASE_CXXFLAGS) -I../includes -I./pch $(WARNINGS) $(PKGCONFIG_CFLAGS) +LIBS = $(PKGCONFIG_LIBS) $(PLATFORM_FLAGS) -l$(BOOST_SYSTEM) -l$(BOOST_THREAD) -l$(BOOST_LOCALE) -l$(BOOST_REGEX) -lstdc++ -lm # these are explicit for clang +LDFLAGS = $(BASE_LDFLAGS) + +ifeq ($(OUTPUT_DIR),) + LIBRARY_DST=$(MODE)/$(LIBRARY) +else + LIBRARY_DST=$(OUTPUT_DIR)/$(LIBRARY) +endif + +all: $(LIBRARY_DST) + +%.h.gch: %.h + @echo "Building precompiled header $(@)" + @$(CXX) -x c++-header $(CXXFLAGS) -c $< -o $@ + +-include $(CPP_DEPENDENCIES) + +%.$(MODE).o: %.cpp + @echo "Compiling $< -> $@" + @$(CXX) -MMD -MF $*.d $(CXXFLAGS) -c $< -o $@ + +$(PRECOMPILED_HEADERS): $(HEADERS) + +$(LIBRARY_DST): $(OBJECTS) + @echo "Building library $@" + @$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $^ -o $@ $(LIBS) + +#DEPS := $(OBJECTS:.o=.d) +#-include $(DEPS) + +clean: + rm $(OBJECTS) $(PRECOMPILED_HEADERS) $(LIBRARY) $(CPP_DEPENDENCIES) + +.SILENT:clean \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/src/authentication.cpp b/Microsoft.WindowsAzure.Storage/src/authentication.cpp index 98771a13..7fdc81d7 100644 --- a/Microsoft.WindowsAzure.Storage/src/authentication.cpp +++ b/Microsoft.WindowsAzure.Storage/src/authentication.cpp @@ -26,11 +26,11 @@ namespace azure { namespace storage { namespace protocol { utility::string_t calculate_hmac_sha256_hash(const utility::string_t& string_to_hash, const storage_credentials& credentials) { - auto utf8_string_to_hash = utility::conversions::to_utf8string(string_to_hash); - auto hash_streambuf = core::hash_hmac_sha256_streambuf(credentials.account_key()); - hash_streambuf.putn(reinterpret_cast(utf8_string_to_hash.data()), utf8_string_to_hash.size()).wait(); - hash_streambuf.close().wait(); - return utility::conversions::to_base64(hash_streambuf.hash()); + std::string utf8_string_to_hash = utility::conversions::to_utf8string(string_to_hash); + core::hash_provider provider = core::hash_provider::create_hmac_sha256_hash_provider(credentials.account_key()); + provider.write(reinterpret_cast(utf8_string_to_hash.data()), utf8_string_to_hash.size()); + provider.close(); + return provider.hash(); } void sas_authentication_handler::sign_request(web::http::http_request& request, operation_context context) const diff --git a/Microsoft.WindowsAzure.Storage/src/basic_types.cpp b/Microsoft.WindowsAzure.Storage/src/basic_types.cpp index e5939f0c..0b67d480 100644 --- a/Microsoft.WindowsAzure.Storage/src/basic_types.cpp +++ b/Microsoft.WindowsAzure.Storage/src/basic_types.cpp @@ -23,21 +23,21 @@ namespace utility { utility::uuid __cdecl new_uuid() { + uuid result; + #ifdef WIN32 RPC_STATUS status; - UUID uuid; - status = UuidCreate(&uuid); + status = UuidCreate(&result); if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY && status != RPC_S_UUID_NO_ADDRESS) { throw std::runtime_error(azure::storage::protocol::error_create_uuid); } #else - uuid_t uuid; - uuid_generate_random(uuid); + uuid_generate_random(result.data); #endif - return uuid; + return result; } utility::string_t __cdecl uuid_to_string(const utility::uuid& value) @@ -61,9 +61,9 @@ namespace utility { } #else char uuid_string[37]; - uuid_unparse_upper(value, uuid_string); + uuid_unparse_upper(value.data, uuid_string); - std::string result(&uuid_string); + std::string result(uuid_string); #endif return result; @@ -71,20 +71,20 @@ namespace utility { utility::uuid __cdecl string_to_uuid(const utility::string_t& value) { + uuid result; + #ifdef WIN32 RPC_STATUS status; RPC_WSTR rpc_string = reinterpret_cast(const_cast(value.c_str())); - UUID result; status = UuidFromStringW(rpc_string, &result); if (status != RPC_S_OK) { throw std::runtime_error(azure::storage::protocol::error_parse_uuid); } #else - uuid_t result; - int status_code = uuid_parse(value.c_str(), result); + int status_code = uuid_parse(value.c_str(), result.data); if (status_code != 0) { throw std::runtime_error(azure::storage::protocol::error_parse_uuid); @@ -99,7 +99,7 @@ namespace utility { #ifdef WIN32 return value1 == value2; #else - return uuid_compare(value1, value2) == 0; + return uuid_compare(value1.data, value2.data) == 0; #endif } diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp index ccab507f..f6f05638 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob.cpp @@ -143,9 +143,9 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_blob_properties, snapshot_time(), condition, 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); - command->set_preprocess_response([properties, metadata, copy_state] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties, metadata, copy_state] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_all(protocol::blob_response_parsers::parse_blob_properties(response), false); *metadata = protocol::parse_metadata(response); *copy_state = protocol::blob_response_parsers::parse_copy_state(response); @@ -164,9 +164,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::set_blob_metadata, metadata(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -183,9 +183,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::set_blob_properties, *properties, metadata(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto parsed_properties = protocol::blob_response_parsers::parse_blob_properties(response); properties->update_etag_and_last_modified(parsed_properties); @@ -202,7 +202,7 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::delete_blob, snapshots_option, snapshot_time(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -257,9 +257,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob, protocol::header_value_lease_acquire, proposed_lease_id, duration, lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> utility::string_t + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); return protocol::parse_lease_id(response); }); @@ -282,9 +282,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob, protocol::header_value_lease_renew, utility::string_t(), lease_time(), lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -306,9 +306,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob, protocol::header_value_lease_change, proposed_lease_id, lease_time(), lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> utility::string_t + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); return protocol::parse_lease_id(response); }); @@ -331,9 +331,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob, protocol::header_value_lease_release, utility::string_t(), lease_time(), lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -350,15 +350,26 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob, protocol::header_value_lease_break, utility::string_t(), lease_time(), break_period, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> std::chrono::seconds + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> std::chrono::seconds { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); return protocol::parse_lease_time(response); }); return core::executor::execute_async(command, modified_options, context); } + struct blob_download_info + { + bool m_are_properties_populated; + utility::size64_t m_total_written_to_destination_stream; + utility::size64_t m_response_length; + utility::string_t m_response_md5; + utility::string_t m_locked_etag; + bool m_reset_target; + concurrency::streams::ostream::pos_type m_target_offset; + }; + pplx::task cloud_blob::download_range_to_stream_async(concurrency::streams::ostream target, utility::size64_t offset, utility::size64_t length, const access_condition& condition, const blob_request_options& options, operation_context context) { blob_request_options modified_options(options); @@ -367,48 +378,132 @@ namespace azure { namespace storage { auto properties = m_properties; auto metadata = m_metadata; auto copy_state = m_copy_state; - auto target_offset = target.can_seek() ? target.tell() : 0; - auto response_md5 = std::make_shared(); - auto response_length = std::make_shared(std::numeric_limits::max()); + const utility::string_t& current_snapshot_time = snapshot_time(); + + std::shared_ptr download_info = std::make_shared(); + download_info->m_are_properties_populated = false; + download_info->m_total_written_to_destination_stream = 0; + download_info->m_response_length = std::numeric_limits::max(); + download_info->m_reset_target = false; + download_info->m_target_offset = target.can_seek() ? target.tell() : (Concurrency::streams::basic_ostream::pos_type)0; + + std::shared_ptr> command = std::make_shared>(uri()); + std::weak_ptr> weak_command(command); + command->set_build_request([offset, length, modified_options, condition, current_snapshot_time, download_info](web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context) -> web::http::http_request + { + utility::size64_t current_offset = offset; + utility::size64_t current_length = length; + if (download_info->m_total_written_to_destination_stream > 0) + { + if (offset == std::numeric_limits::max()) + { + current_offset = 0; + } - auto command = std::make_shared>(uri()); - command->set_build_request(std::bind(protocol::get_blob, offset, length, modified_options.use_transactional_md5(), snapshot_time(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + current_offset += download_info->m_total_written_to_destination_stream; + + if (length > 0) + { + current_length -= download_info->m_total_written_to_destination_stream; + + if (current_length <= 0) + { + // The entire blob has already been downloaded + throw std::invalid_argument("offset"); + } + } + } + + access_condition current_condition; + if (download_info->m_are_properties_populated && !download_info->m_locked_etag.empty()) + { + current_condition.set_if_match_etag(download_info->m_locked_etag); + + if (!condition.lease_id().empty()) + { + current_condition.set_lease_id(condition.lease_id()); + } + } + else + { + current_condition = condition; + } + + return protocol::get_blob(current_offset, current_length, modified_options.use_transactional_md5() && !download_info->m_are_properties_populated, current_snapshot_time, current_condition, uri_builder, timeout, context); + }); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(core::command_location_mode::primary_or_secondary); command->set_destination_stream(target); command->set_calculate_response_body_md5(!modified_options.disable_content_md5_validation()); - command->set_recover_request([target, target_offset] (operation_context context) -> bool + command->set_recover_request([target, download_info](utility::size64_t total_written_to_destination_stream, operation_context context) -> bool { - // TODO support resume - if (target.can_seek()) + if (download_info->m_reset_target) { - target.seek(target_offset); - return true; + download_info->m_total_written_to_destination_stream = 0; + + if (total_written_to_destination_stream > 0) + { + if (!target.can_seek()) + { + return false; + } + + target.seek(download_info->m_target_offset); + } + + download_info->m_reset_target = false; } else { - return false; + download_info->m_total_written_to_destination_stream = total_written_to_destination_stream; } + + return true; }); - command->set_preprocess_response([modified_options, properties, metadata, copy_state, offset, response_md5, response_length] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([weak_command, offset, modified_options, properties, metadata, copy_state, download_info](const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); - properties->update_all(protocol::blob_response_parsers::parse_blob_properties(response), offset < std::numeric_limits::max()); - *metadata = protocol::parse_metadata(response); - *copy_state = protocol::blob_response_parsers::parse_copy_state(response); - - *response_md5 = protocol::get_header_value(response, web::http::header_names::content_md5); - - if (modified_options.use_transactional_md5() && !modified_options.disable_content_md5_validation() && response_md5->empty()) + std::shared_ptr> command(weak_command); + + protocol::preprocess_response_void(response, result, context); + + if (!download_info->m_are_properties_populated) { - throw storage_exception(protocol::error_missing_md5); - } + properties->update_all(protocol::blob_response_parsers::parse_blob_properties(response), offset != std::numeric_limits::max()); + *metadata = protocol::parse_metadata(response); + *copy_state = protocol::blob_response_parsers::parse_copy_state(response); + + download_info->m_response_length = result.content_length(); + download_info->m_response_md5 = result.content_md5(); + + if (modified_options.use_transactional_md5() && !modified_options.disable_content_md5_validation() && download_info->m_response_md5.empty()) + { + throw storage_exception(protocol::error_missing_md5); + } + + // Lock to the current storage location when resuming a failed download. This is locked + // early before the retry policy has the opportunity to change the storage location. + command->set_location_mode(core::command_location_mode::primary_or_secondary, result.target_location()); - *response_length = response.headers().content_length(); + download_info->m_locked_etag = properties->etag(); + download_info->m_are_properties_populated = true; + } }); - command->set_postprocess_response([response_md5, response_length] (const web::http::http_response&, const request_result&, const core::ostream_descriptor& descriptor, operation_context context) -> pplx::task + command->set_postprocess_response([weak_command, download_info](const web::http::http_response&, const request_result&, const core::ostream_descriptor& descriptor, operation_context context) -> pplx::task { - protocol::check_stream_length_and_md5(*response_length, *response_md5, descriptor); + std::shared_ptr> command(weak_command); + + // Start the download over from the beginning if a retry is needed again because the last + // response was successfully downloaded and the MD5 hash has already been calculated + download_info->m_reset_target = true; + download_info->m_are_properties_populated = false; + + command->set_location_mode(core::command_location_mode::primary_or_secondary); + + if (!download_info->m_response_md5.empty() && !descriptor.content_md5().empty() && download_info->m_response_md5 != descriptor.content_md5()) + { + throw storage_exception(protocol::error_md5_mismatch); + } + return pplx::task_from_result(); }); return core::executor::execute_async(command, modified_options, context); @@ -442,14 +537,14 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_blob_properties, snapshot_time(), access_condition(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(primary_only ? core::command_location_mode::primary_only : core::command_location_mode::primary_or_secondary); - command->set_preprocess_response([properties, metadata, copy_state] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([properties, metadata, copy_state] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (response.status_code() == web::http::status_codes::NotFound) { return false; } - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_all(protocol::blob_response_parsers::parse_blob_properties(response), false); *metadata = protocol::parse_metadata(response); *copy_state = protocol::blob_response_parsers::parse_copy_state(response); @@ -470,9 +565,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::copy_blob, source, source_condition, metadata(), destination_condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties, copy_state] (const web::http::http_response& response, operation_context context) -> utility::string_t + command->set_preprocess_response([properties, copy_state] (const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); auto new_state = protocol::blob_response_parsers::parse_copy_state(response); *copy_state = new_state; @@ -498,7 +593,7 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::abort_copy_blob, copy_id, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -517,9 +612,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::snapshot_blob, *snapshot_metadata, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([snapshot_name, snapshot_container, resulting_metadata, properties] (const web::http::http_response& response, operation_context context) -> cloud_blob + command->set_preprocess_response([snapshot_name, snapshot_container, resulting_metadata, properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> cloud_blob { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto snapshot_time = protocol::get_header_value(response, protocol::ms_header_snapshot); cloud_blob snapshot(snapshot_name, snapshot_time, snapshot_container); *snapshot.m_metadata = *resulting_metadata; diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp index 580b3eda..6d62c56b 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_client.cpp @@ -33,21 +33,21 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::list_containers, prefix, includes, max_results, token, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(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, container_result_segment(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, container_result_segment(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([client] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task { protocol::list_containers_reader reader(response.body()); // TODO: Initialize a reasonable capacity for container objects throughout the codebase - std::vector items(reader.extract_items()); + std::vector items(reader.move_items()); std::vector results; for (std::vector::iterator iter = items.begin(); iter != items.end(); ++iter) { - results.push_back(cloud_blob_container(iter->name(), client, iter->properties(), iter->metadata())); + results.push_back(cloud_blob_container(iter->move_name(), client, iter->move_properties(), iter->move_metadata())); } - continuation_token next_token(reader.extract_next_marker()); + continuation_token next_token(reader.move_next_marker()); next_token.set_target_location(result.target_location()); return pplx::task_from_result(container_result_segment(std::move(results), next_token)); }); diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp index 3b93c674..a956eeda 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_container.cpp @@ -122,9 +122,9 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_blob_container_properties, condition, 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); - command->set_preprocess_response([properties, metadata] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties, metadata] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); *properties = protocol::blob_response_parsers::parse_blob_container_properties(response); *metadata = protocol::parse_metadata(response); }); @@ -141,9 +141,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::set_blob_container_metadata, metadata(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -159,9 +159,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob_container, protocol::header_value_lease_acquire, proposed_lease_id, duration, lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> utility::string_t + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); return protocol::parse_lease_id(response); }); @@ -183,9 +183,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob_container, protocol::header_value_lease_renew, utility::string_t(), lease_time(), lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -206,9 +206,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob_container, protocol::header_value_lease_change, proposed_lease_id, lease_time(), lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> utility::string_t + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> utility::string_t { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); return protocol::parse_lease_id(response); }); @@ -230,9 +230,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob_container, protocol::header_value_lease_release, utility::string_t(), lease_time(), lease_break_period(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -248,9 +248,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::lease_blob_container, protocol::header_value_lease_break, utility::string_t(), lease_time(), break_period, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> std::chrono::seconds + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> std::chrono::seconds { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); return protocol::parse_lease_time(response); }); @@ -267,9 +267,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::create_blob_container, public_access, metadata(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); }); return core::executor::execute_async(command, modified_options, context); @@ -323,7 +323,7 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::delete_blob_container, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -389,26 +389,26 @@ namespace azure { namespace storage { 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)); + 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 { protocol::list_blobs_reader reader(response.body()); - std::vector blob_items(reader.extract_blob_items()); + std::vector blob_items(reader.move_blob_items()); std::vector blobs; for (std::vector::iterator iter = blob_items.begin(); iter != blob_items.end(); ++iter) { - blobs.push_back(cloud_blob(iter->name(), iter->snapshot_time(), container, iter->properties(), iter->metadata(), iter->copy_state())); + blobs.push_back(cloud_blob(iter->move_name(), iter->move_snapshot_time(), container, iter->move_properties(), iter->move_metadata(), iter->move_copy_state())); } - std::vector blob_prefix_items(reader.extract_blob_prefix_items()); + std::vector blob_prefix_items(reader.move_blob_prefix_items()); std::vector directories; for (auto iter = blob_prefix_items.begin(); iter != blob_prefix_items.end(); ++iter) { - directories.push_back(cloud_blob_directory(iter->name(), container)); + directories.push_back(cloud_blob_directory(iter->move_name(), container)); } - continuation_token next_token(reader.extract_next_marker()); + 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)); }); @@ -428,9 +428,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::set_blob_container_acl, permissions.public_access(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); }); return core::istream_descriptor::create(stream).then([command, context, modified_options] (core::istream_descriptor request_body) -> pplx::task @@ -451,9 +451,9 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_blob_container_acl, condition, 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); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> blob_container_permissions + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> blob_container_permissions { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_container_properties(response)); return blob_container_permissions(); }); @@ -461,7 +461,7 @@ namespace azure { namespace storage { { blob_container_permissions permissions; protocol::access_policy_reader reader(response.body()); - permissions.set_policies(reader.extract_policies()); + permissions.set_policies(reader.move_policies()); permissions.set_public_access(protocol::blob_response_parsers::parse_public_access_type(response)); return pplx::task_from_result(permissions); }); @@ -480,14 +480,14 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_blob_container_properties, access_condition(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(primary_only ? core::command_location_mode::primary_only : core::command_location_mode::primary_or_secondary); - command->set_preprocess_response([properties, metadata] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([properties, metadata] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (response.status_code() == web::http::status_codes::NotFound) { return false; } - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); *properties = protocol::blob_response_parsers::parse_blob_container_properties(response); *metadata = protocol::parse_metadata(response); return true; diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_istreambuf.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_istreambuf.cpp index 43d2b999..3de90478 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_istreambuf.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_istreambuf.cpp @@ -17,6 +17,7 @@ #include "stdafx.h" #include "wascore/blobstreams.h" +#include "wascore/resources.h" namespace azure { namespace storage { namespace core { @@ -36,7 +37,7 @@ namespace azure { namespace storage { namespace core { m_current_blob_offset = pos; m_next_blob_offset = m_current_blob_offset; m_buffer = concurrency::streams::container_buffer>(std::ios_base::in); - m_blob_hash = hash_streambuf(); + m_blob_hash_provider = hash_provider(); return pos; } } @@ -146,27 +147,23 @@ namespace azure { namespace storage { namespace core { this_pointer->m_buffer = concurrency::streams::container_buffer>(std::move(temp_buffer.collection()), std::ios_base::in); this_pointer->m_buffer.seekpos(0, std::ios_base::in); - if (this_pointer->m_blob_hash && this_pointer->m_blob_hash.is_open()) + // Validate the blob's content MD5 hash + if (this_pointer->m_blob_hash_provider.is_enabled()) { - return this_pointer->m_buffer.create_istream().read_to_end(this_pointer->m_blob_hash).then([this_pointer] (size_t) -> bool + std::vector& result_buffer = this_pointer->m_buffer.collection(); + this_pointer->m_blob_hash_provider.write(result_buffer.data(), result_buffer.size()); + + if (((utility::size64_t) this_pointer->m_next_blob_offset) == this_pointer->size()) { - if (((utility::size64_t) this_pointer->m_next_blob_offset) == this_pointer->size()) + this_pointer->m_blob_hash_provider.close(); + if (this_pointer->m_blob->properties().content_md5() != this_pointer->m_blob_hash_provider.hash()) { - this_pointer->m_blob_hash.close().wait(); - if (this_pointer->m_blob->properties().content_md5() != utility::conversions::to_base64(this_pointer->m_blob_hash.hash())) - { - throw storage_exception(protocol::error_md5_mismatch); - } + throw storage_exception(protocol::error_md5_mismatch); } - - this_pointer->m_buffer.seekpos(0, std::ios_base::in); - return true; - }); - } - else - { - return pplx::task_from_result(true); + } } + + return pplx::task_from_result(true); } catch (const std::exception&) { diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_blob_ostreambuf.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_blob_ostreambuf.cpp index 0556265e..a6c22544 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_blob_ostreambuf.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_blob_ostreambuf.cpp @@ -17,6 +17,7 @@ #include "stdafx.h" #include "wascore/blobstreams.h" +#include "wascore/resources.h" namespace azure { namespace storage { namespace core { @@ -30,9 +31,9 @@ namespace azure { namespace storage { namespace core { m_committed = true; basic_ostreambuf::_close_write().wait(); - if (m_blob_hash) + if (m_blob_hash_provider.is_enabled()) { - m_blob_hash.close().wait(); + m_blob_hash_provider.close(); } return commit_blob(); @@ -59,11 +60,11 @@ namespace azure { namespace storage { namespace core { std::shared_ptr basic_cloud_blob_ostreambuf::prepare_buffer() { utility::string_t block_md5; - if (m_block_hash) + if (m_block_hash_provider.is_enabled()) { - m_block_hash.close().wait(); - block_md5 = utility::conversions::to_base64(m_block_hash.hash()); - m_block_hash = hash_md5_streambuf(); + m_block_hash_provider.close(); + block_md5 = m_block_hash_provider.hash(); + m_block_hash_provider = hash_provider::create_md5_hash_provider(); } auto buffer = std::make_shared(m_buffer, block_md5); @@ -102,19 +103,17 @@ namespace azure { namespace storage { namespace core { write_size = remaining; } - // All streambuf puts below are waited, because one is a memory buffer and the others - // are hash buffers. Hence, there is no async IO involved. - - if (m_block_hash) + if (m_block_hash_provider.is_enabled()) { - m_block_hash.putn(ptr, write_size).wait(); + m_block_hash_provider.write(ptr, write_size); } - if (m_blob_hash) + if (m_blob_hash_provider.is_enabled()) { - m_blob_hash.putn(ptr, write_size).wait(); + m_blob_hash_provider.write(ptr, write_size); } + // The streambuf is waited because it is a memory buffer, so does not involve async I/O m_buffer.putn(ptr, write_size).wait(); if (m_buffer_size == m_buffer.size()) { @@ -178,9 +177,9 @@ namespace azure { namespace storage { namespace core { auto this_pointer = std::dynamic_pointer_cast(shared_from_this()); return _sync().then([this_pointer] (bool) -> pplx::task { - if (this_pointer->m_blob_hash) + if (this_pointer->m_blob_hash_provider.is_enabled()) { - this_pointer->m_blob->properties().set_content_md5(utility::conversions::to_base64(this_pointer->m_blob_hash.hash())); + this_pointer->m_blob->properties().set_content_md5(this_pointer->m_blob_hash_provider.hash()); } return this_pointer->m_blob->upload_block_list_async(this_pointer->m_block_list, this_pointer->m_condition, this_pointer->m_options, this_pointer->m_context); @@ -243,12 +242,12 @@ namespace azure { namespace storage { namespace core { pplx::task basic_cloud_page_blob_ostreambuf::commit_blob() { - if (m_blob_hash) + if (m_blob_hash_provider.is_enabled()) { auto this_pointer = std::dynamic_pointer_cast(shared_from_this()); return _sync().then([this_pointer] (bool) -> pplx::task { - this_pointer->m_blob->properties().set_content_md5(utility::conversions::to_base64(this_pointer->m_blob_hash.hash())); + this_pointer->m_blob->properties().set_content_md5(this_pointer->m_blob_hash_provider.hash()); return this_pointer->m_blob->upload_properties_async(this_pointer->m_condition, this_pointer->m_options, this_pointer->m_context); }); } diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_block_blob.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_block_blob.cpp index d86fa07e..22b5d5d3 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_block_blob.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_block_blob.cpp @@ -32,7 +32,7 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::istream_descriptor::create(block_data, needs_md5).then([command, context, block_id, content_md5, modified_options, condition] (core::istream_descriptor request_body) -> pplx::task { const utility::string_t& md5 = content_md5.empty() ? request_body.content_md5() : content_md5; @@ -56,9 +56,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::put_block_list, *properties, metadata(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); }); return core::istream_descriptor::create(stream).then([command, context, modified_options] (core::istream_descriptor request_body) -> pplx::task @@ -79,16 +79,16 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_block_list, listing_filter, snapshot_time(), condition, 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); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> std::vector + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> std::vector { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); return std::vector(); }); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task> { protocol::block_list_reader reader(response.body()); - return pplx::task_from_result(reader.extract_result()); + return pplx::task_from_result(reader.move_result()); }); return core::executor>::execute_async(command, modified_options, context); } @@ -143,9 +143,20 @@ namespace azure { namespace storage { blob_request_options modified_options(options); modified_options.apply_defaults(service_client().default_request_options(), type()); + // This will be std::numeric_limits::max() if the stream is not seekable. + utility::size64_t remaining_stream_length = core::get_remaining_stream_length(source); + + // Before this line, 'length = max' means "no length was given by the user." After this line, 'length = max' means "no length was given, and the stream is not seekable." if (length == std::numeric_limits::max()) { - length = core::get_remaining_stream_length(source); + length = remaining_stream_length; + } + + // If the stream is seekable, check for the case where the stream is too short. + // If the stream is not seekable, this will be caught later, when we run out of bytes in the stream when uploading. + if (source.can_seek() && (length > remaining_stream_length)) + { + throw std::invalid_argument(protocol::error_stream_short); } if ((length != std::numeric_limits::max()) && @@ -162,9 +173,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); }); return core::istream_descriptor::create(source, modified_options.store_blob_content_md5(), length).then([command, context, properties, metadata, condition, modified_options] (core::istream_descriptor request_body) -> pplx::task diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_client.cpp index d687a52f..19d36bd0 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_client.cpp @@ -28,11 +28,11 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_service_properties, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(authentication_handler()); command->set_location_mode(core::command_location_mode::primary_or_secondary); - command->set_preprocess_response(std::bind(protocol::preprocess_response, service_properties(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, service_properties(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { protocol::service_properties_reader reader(response.body()); - return pplx::task_from_result(reader.extract_properties()); + return pplx::task_from_result(reader.move_properties()); }); return core::executor::execute_async(command, modified_options, context); } @@ -45,7 +45,7 @@ namespace azure { namespace storage { auto command = std::make_shared>(base_uri()); command->set_build_request(std::bind(protocol::set_service_properties, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::istream_descriptor::create(stream).then([command, context, modified_options] (core::istream_descriptor request_body) -> pplx::task { command->set_request_body(request_body); @@ -59,11 +59,11 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_service_stats, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(authentication_handler()); command->set_location_mode(core::command_location_mode::primary_or_secondary); - command->set_preprocess_response(std::bind(protocol::preprocess_response, service_stats(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, service_stats(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { protocol::service_stats_reader reader(response.body()); - return pplx::task_from_result(reader.extract_stats()); + return pplx::task_from_result(reader.move_stats()); }); return core::executor::execute_async(command, modified_options, context); } diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_common.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_common.cpp new file mode 100644 index 00000000..60bae534 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/src/cloud_common.cpp @@ -0,0 +1,30 @@ +// ----------------------------------------------------------------------------------------- +// +// 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 "was/common.h" + +namespace azure { namespace storage { + + WASTORAGE_API request_options::request_options() + : m_location_mode(azure::storage::location_mode::primary_only), m_retry_policy(exponential_retry_policy()), m_http_buffer_size(protocol::default_buffer_size),\ + m_maximum_execution_time(protocol::default_maximum_execution_time), m_server_timeout(protocol::default_server_timeout) + { + } + +}} // namespace azure::storage diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_page_blob.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_page_blob.cpp index cce3d806..90eb4cfe 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_page_blob.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_page_blob.cpp @@ -36,9 +36,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::put_page, range, page_write::clear, utility::string_t(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto parsed_properties = protocol::blob_response_parsers::parse_blob_properties(response); properties->update_etag_and_last_modified(parsed_properties); @@ -58,9 +58,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto parsed_properties = protocol::blob_response_parsers::parse_blob_properties(response); properties->update_etag_and_last_modified(parsed_properties); @@ -158,9 +158,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::put_page_blob, size, *properties, metadata(), condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties, size] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties, size] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response)); properties->m_size = size; }); @@ -178,9 +178,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::resize_page_blob, size, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties, size] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties, size] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto parsed_properties = protocol::blob_response_parsers::parse_blob_properties(response); properties->update_etag_and_last_modified(parsed_properties); @@ -201,9 +201,9 @@ namespace azure { namespace storage { auto command = std::make_shared>(uri()); command->set_build_request(std::bind(protocol::set_page_blob_sequence_number, sequence_number, condition, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto parsed_properties = protocol::blob_response_parsers::parse_blob_properties(response); properties->update_etag_and_last_modified(parsed_properties); @@ -223,9 +223,9 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_page_ranges, offset, length, snapshot_time(), condition, 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); - command->set_preprocess_response([properties] (const web::http::http_response& response, operation_context context) -> std::vector + command->set_preprocess_response([properties] (const web::http::http_response& response, const request_result& result, operation_context context) -> std::vector { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); auto parsed_properties = protocol::blob_response_parsers::parse_blob_properties(response); properties->update_etag_and_last_modified(parsed_properties); @@ -234,8 +234,9 @@ namespace azure { namespace storage { }); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task> { + UNREFERENCED_PARAMETER(context); protocol::page_list_reader reader(response.body()); - return pplx::task_from_result(reader.extract_result()); + return pplx::task_from_result(reader.move_result()); }); return core::executor>::execute_async(command, modified_options, context); } diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_queue.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_queue.cpp index 4b35af15..5303b835 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_queue.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_queue.cpp @@ -113,7 +113,7 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::add_message, message, time_to_live, initial_visibility_timeout, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -135,16 +135,17 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::get_messages, 1U, visibility_timeout, /* is_peek */ false, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, cloud_queue_message(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, cloud_queue_message(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); protocol::message_reader reader(response.body()); - std::vector queue_items = reader.extract_items(); + std::vector queue_items = reader.move_items(); if (!queue_items.empty()) { protocol::cloud_message_list_item& item = queue_items.front(); - cloud_queue_message message(item.content(), item.id(), item.pop_receipt(), item.insertion_time(), item.expiration_time(), item.next_visible_time(), item.dequeue_count()); + cloud_queue_message message(item.move_content(), item.move_id(), item.move_pop_receipt(), item.insertion_time(), item.expiration_time(), item.next_visible_time(), item.dequeue_count()); return pplx::task_from_result(message); } @@ -176,18 +177,19 @@ namespace azure { namespace storage { std::shared_ptr>> command = std::make_shared>>(uri); command->set_build_request(std::bind(protocol::get_messages, message_count, visibility_timeout, /* is_peek */ false, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response>, std::vector(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response>, std::vector(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task> { + UNREFERENCED_PARAMETER(context); protocol::message_reader reader(response.body()); - std::vector queue_items = reader.extract_items(); + std::vector queue_items = reader.move_items(); std::vector results; results.reserve(queue_items.size()); for (std::vector::iterator it = queue_items.begin(); it != queue_items.end(); ++it) { - cloud_queue_message message(it->content(), it->id(), it->pop_receipt(), it->insertion_time(), it->expiration_time(), it->next_visible_time(), it->dequeue_count()); + cloud_queue_message message(it->move_content(), it->move_id(), it->move_pop_receipt(), it->insertion_time(), it->expiration_time(), it->next_visible_time(), it->dequeue_count()); results.push_back(message); } @@ -204,16 +206,17 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::get_messages, 1U, std::chrono::seconds(0LL), /* is_peek */ true, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, cloud_queue_message(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, cloud_queue_message(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); protocol::message_reader reader(response.body()); - std::vector queue_items = reader.extract_items(); + std::vector queue_items = reader.move_items(); if (!queue_items.empty()) { protocol::cloud_message_list_item& item = queue_items.front(); - cloud_queue_message message(item.content(), item.id(), item.pop_receipt(), item.insertion_time(), item.expiration_time(), item.next_visible_time(), item.dequeue_count()); + cloud_queue_message message(item.move_content(), item.move_id(), item.move_pop_receipt(), item.insertion_time(), item.expiration_time(), item.next_visible_time(), item.dequeue_count()); return pplx::task_from_result(message); } @@ -230,18 +233,19 @@ namespace azure { namespace storage { std::shared_ptr>> command = std::make_shared>>(uri); command->set_build_request(std::bind(protocol::get_messages, message_count, std::chrono::seconds(0LL), /* is_peek */ true, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response>, std::vector(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response>, std::vector(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task> { + UNREFERENCED_PARAMETER(context); protocol::message_reader reader(response.body()); - std::vector queue_items = reader.extract_items(); + std::vector queue_items = reader.move_items(); std::vector results; results.reserve(queue_items.size()); for (std::vector::iterator it = queue_items.begin(); it != queue_items.end(); ++it) { - cloud_queue_message message(it->content(), it->id(), it->pop_receipt(), it->insertion_time(), it->expiration_time(), it->next_visible_time(), it->dequeue_count()); + cloud_queue_message message(it->move_content(), it->move_id(), it->move_pop_receipt(), it->insertion_time(), it->expiration_time(), it->next_visible_time(), it->dequeue_count()); results.push_back(message); } @@ -278,9 +282,9 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::update_message, message, visibility_timeout, update_content, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([&message] (const web::http::http_response& response, operation_context context) mutable + command->set_preprocess_response([&message] (const web::http::http_response& response, const request_result& result, operation_context context) mutable { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); message.set_pop_receipt(protocol::parse_pop_receipt(response)); message.set_next_visible_time(protocol::parse_next_visible_time(response)); }); @@ -295,7 +299,7 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::delete_message, message, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -307,7 +311,7 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::clear_messages, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -320,9 +324,9 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::download_queue_metadata, 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); - command->set_preprocess_response([this](const web::http::http_response& response, operation_context context) + command->set_preprocess_response([this](const web::http::http_response& response, const request_result& result, operation_context context) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); m_metadata = protocol::parse_metadata(response); m_approximate_message_count = protocol::parse_approximate_messages_count(response); }); @@ -337,7 +341,7 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::upload_queue_metadata, metadata(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::executor::execute_async(command, modified_options, context); } @@ -350,12 +354,13 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_queue_acl, 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); - command->set_preprocess_response(std::bind(protocol::preprocess_response, queue_permissions(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, queue_permissions(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); queue_permissions permissions; protocol::access_policy_reader reader(response.body()); - permissions.set_policies(reader.extract_policies()); + permissions.set_policies(reader.move_policies()); return pplx::task_from_result(permissions); }); return core::executor::execute_async(command, modified_options, context); @@ -372,7 +377,7 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::set_queue_acl, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::istream_descriptor::create(stream).then([command, context, modified_options](core::istream_descriptor request_body) -> pplx::task { command->set_request_body(request_body); @@ -432,14 +437,14 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::create_queue, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([allow_conflict] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([allow_conflict] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if ((allow_conflict && response.status_code() == web::http::status_codes::Conflict) || response.status_code() == web::http::status_codes::NoContent) { return false; } - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); return true; }); return core::executor::execute_async(command, modified_options, context); @@ -453,14 +458,14 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::delete_queue, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([allow_not_found] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([allow_not_found] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (allow_not_found && response.status_code() == web::http::status_codes::NotFound) { return false; } - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); return true; }); return core::executor::execute_async(command, modified_options, context); @@ -475,11 +480,11 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::download_queue_metadata, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(allow_secondary ? core::command_location_mode::primary_or_secondary : core::command_location_mode::primary_only); - command->set_preprocess_response([] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (response.status_code() != web::http::status_codes::NotFound) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); return true; } diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp index 0a16d3be..fbc245e3 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_queue_client.cpp @@ -61,27 +61,28 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::list_queues, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(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, queue_result_segment(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, queue_result_segment(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([this, get_metadata] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); protocol::list_queues_reader reader(response.body()); - std::vector queue_items = reader.extract_items(); + std::vector queue_items = reader.move_items(); std::vector results; results.reserve(queue_items.size()); for (std::vector::iterator it = queue_items.begin(); it != queue_items.end(); ++it) { - cloud_queue queue = get_queue_reference(it->name()); + cloud_queue queue = get_queue_reference(it->move_name()); if (get_metadata) { - queue.set_metadata(it->metadata()); + queue.set_metadata(it->move_metadata()); } results.push_back(std::move(queue)); } - utility::string_t next_marker = reader.extract_next_marker(); + utility::string_t next_marker = reader.move_next_marker(); if (!next_marker.empty()) { next_marker = core::make_query_parameter(protocol::queue_query_next_marker, next_marker); diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp index 004a8ee4..c97692b5 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_table.cpp @@ -33,9 +33,9 @@ namespace azure { namespace storage { const utility::string_t query_comparison_operator::less_than = U("lt"); const utility::string_t query_comparison_operator::less_than_or_equal = U("le"); - const utility::string_t query_logical_operator::and = U("and"); - const utility::string_t query_logical_operator::not = U("not"); - const utility::string_t query_logical_operator::or = U("or"); + const utility::string_t query_logical_operator::op_and = U("and"); + const utility::string_t query_logical_operator::op_not = U("not"); + const utility::string_t query_logical_operator::op_or = U("or"); cloud_table::cloud_table(const storage_uri& uri) : m_client(create_service_client(uri, storage_credentials())), m_name(read_table_name(uri)), m_uri(create_uri(uri)) @@ -109,16 +109,17 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::execute_operation, operation, options.payload_format(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(operation.operation_type() == azure::storage::table_operation_type::retrieve_operation ? core::command_location_mode::primary_or_secondary : core::command_location_mode::primary_only); - command->set_preprocess_response([allow_not_found] (const web::http::http_response& response, operation_context context) -> table_result + command->set_preprocess_response([allow_not_found] (const web::http::http_response& response, const request_result& result, operation_context context) -> table_result { if (!allow_not_found || response.status_code() != web::http::status_codes::NotFound) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); } return table_result(); }); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); int status_code = response.status_code(); utility::string_t etag = protocol::table_response_parsers::parse_etag(response); @@ -196,10 +197,11 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::execute_batch_operation, response_buffer, *this, operation, options.payload_format(), is_query, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(is_query ? core::command_location_mode::primary_or_secondary : core::command_location_mode::primary_only); - command->set_preprocess_response(std::bind(protocol::preprocess_response>, std::vector(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response>, std::vector(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([response_buffer, operations, is_query] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) mutable -> pplx::task> { - return response.content_ready().then([response_buffer, operations, is_query] (const web::http::http_response& response) mutable -> pplx::task> + UNREFERENCED_PARAMETER(context); + return response.content_ready().then([response_buffer, operations, is_query](const web::http::http_response& response) mutable -> pplx::task> { std::vector batch_result = protocol::table_response_parsers::parse_batch_results(response, response_buffer, is_query, operations.size()); return pplx::task_from_result(batch_result); @@ -237,9 +239,10 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::execute_query, options.payload_format(), 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, table_query_segment(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, table_query_segment(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); continuation_token next_token = protocol::table_response_parsers::parse_continuation_token(response, result); return response.extract_json().then([next_token] (const web::json::value& obj) -> table_query_segment @@ -306,14 +309,14 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::execute_table_operation, *this, table_operation_type::insert_operation, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([allow_conflict] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([allow_conflict] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (allow_conflict && response.status_code() == web::http::status_codes::Conflict) { return false; } - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); return true; }); return core::executor::execute_async(command, modified_options, context); @@ -327,14 +330,14 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::execute_table_operation, *this, table_operation_type::delete_operation, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response([allow_not_found] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([allow_not_found] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (allow_not_found && response.status_code() == web::http::status_codes::NotFound) { return false; } - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); return true; }); return core::executor::execute_async(command, modified_options, context); @@ -349,11 +352,11 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::execute_table_operation, *this, table_operation_type::retrieve_operation, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); command->set_location_mode(allow_secondary ? core::command_location_mode::primary_or_secondary : core::command_location_mode::primary_only); - command->set_preprocess_response([] (const web::http::http_response& response, operation_context context) -> bool + command->set_preprocess_response([] (const web::http::http_response& response, const request_result& result, operation_context context) -> bool { if (response.status_code() != web::http::status_codes::NotFound) { - protocol::preprocess_response(response, context); + protocol::preprocess_response_void(response, result, context); return true; } @@ -371,12 +374,13 @@ namespace azure { namespace storage { command->set_build_request(std::bind(protocol::get_table_acl, 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); - command->set_preprocess_response(std::bind(protocol::preprocess_response, table_permissions(), std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response, table_permissions(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_postprocess_response([] (const web::http::http_response& response, const request_result&, const core::ostream_descriptor&, operation_context context) -> pplx::task { + UNREFERENCED_PARAMETER(context); table_permissions permissions; protocol::access_policy_reader reader(response.body()); - permissions.set_policies(reader.extract_policies()); + permissions.set_policies(reader.move_policies()); return pplx::task_from_result(permissions); }); return core::executor::execute_async(command, modified_options, context); @@ -393,7 +397,7 @@ namespace azure { namespace storage { std::shared_ptr> command = std::make_shared>(uri); command->set_build_request(std::bind(protocol::set_table_acl, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); command->set_authentication_handler(service_client().authentication_handler()); - command->set_preprocess_response(std::bind(protocol::preprocess_response, std::placeholders::_1, std::placeholders::_2)); + command->set_preprocess_response(std::bind(protocol::preprocess_response_void, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return core::istream_descriptor::create(stream).then([command, context, modified_options] (core::istream_descriptor request_body) -> pplx::task { command->set_request_body(request_body); diff --git a/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp b/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp index c9c01d5a..e680ca67 100644 --- a/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp +++ b/Microsoft.WindowsAzure.Storage/src/cloud_table_client.cpp @@ -67,7 +67,7 @@ namespace azure { namespace storage { { utility::string_t filter_string = table_query::combine_filter_conditions( table_query::generate_filter_condition(U("TableName"), query_comparison_operator::greater_than_or_equal, prefix), - query_logical_operator::and, + query_logical_operator::op_and, table_query::generate_filter_condition(U("TableName"), query_comparison_operator::less_than, prefix + U('{'))); query.set_filter_string(filter_string); } diff --git a/Microsoft.WindowsAzure.Storage/src/hashing.cpp b/Microsoft.WindowsAzure.Storage/src/hashing.cpp new file mode 100644 index 00000000..ce9c1d50 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/src/hashing.cpp @@ -0,0 +1,146 @@ +// ----------------------------------------------------------------------------------------- +// +// 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/hashing.h" + +namespace azure { namespace storage { namespace core { + +#ifdef WIN32 + + cryptography_hash_algorithm::cryptography_hash_algorithm(LPCWSTR algorithm_id, ULONG flags) + { + NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algorithm_handle, algorithm_id, NULL, flags); + if (status != 0) + { + throw utility::details::create_system_error(status); + } + } + + cryptography_hash_algorithm::~cryptography_hash_algorithm() + { + BCryptCloseAlgorithmProvider(m_algorithm_handle, 0); + } + + hmac_sha256_hash_algorithm hmac_sha256_hash_algorithm::m_instance; + + md5_hash_algorithm md5_hash_algorithm::m_instance; + + cryptography_hash_provider_impl::cryptography_hash_provider_impl(const cryptography_hash_algorithm& algorithm, const std::vector& key) + { + DWORD hash_object_size = 0; + DWORD data_length = 0; + NTSTATUS status = BCryptGetProperty(algorithm, 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(algorithm, &m_hash_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); + } + } + + cryptography_hash_provider_impl::~cryptography_hash_provider_impl() + { + BCryptDestroyHash(m_hash_handle); + } + + void cryptography_hash_provider_impl::write(const uint8_t* data, size_t count) + { + NTSTATUS status = BCryptHashData(m_hash_handle, (PBYTE)data, (ULONG)count, 0); + if (status != 0) + { + throw utility::details::create_system_error(status); + } + } + + void cryptography_hash_provider_impl::close() + { + DWORD hash_length = 0; + DWORD data_length = 0; + NTSTATUS status = BCryptGetProperty(m_hash_handle, BCRYPT_HASH_LENGTH, (PBYTE)&hash_length, sizeof(DWORD), &data_length, 0); + if (status != 0) + { + throw utility::details::create_system_error(status); + } + + m_hash.resize(hash_length); + + status = BCryptFinishHash(m_hash_handle, m_hash.data(), (ULONG)m_hash.size(), 0); + + // Don't throw an exception if status is success (0), or if the hash was already closed (0x c000 0008) + if ((status != 0) && (status != 0xc0000008)) + { + throw utility::details::create_system_error(status); + } + } + + hmac_sha256_hash_provider_impl::hmac_sha256_hash_provider_impl(const std::vector& key) + : cryptography_hash_provider_impl(hmac_sha256_hash_algorithm::instance(), key) + { + } + + md5_hash_provider_impl::md5_hash_provider_impl() + : cryptography_hash_provider_impl(md5_hash_algorithm::instance(), std::vector()) + { + } + +#else // Linux + + hmac_sha256_hash_provider_impl::hmac_sha256_hash_provider_impl(const std::vector& key) + { + HMAC_CTX_init(&m_hash_context); + HMAC_Init_ex(&m_hash_context, &key[0], (int) key.size(), EVP_sha256(), NULL); + } + + void hmac_sha256_hash_provider_impl::write(const uint8_t* data, size_t count) + { + HMAC_Update(&m_hash_context, data, count); + } + + void hmac_sha256_hash_provider_impl::close() + { + unsigned int length = SHA256_DIGEST_LENGTH; + m_hash.resize(length); + HMAC_Final(&m_hash_context, &m_hash[0], &length); + HMAC_CTX_cleanup(&m_hash_context); + } + + md5_hash_provider_impl::md5_hash_provider_impl() + { + MD5_Init(&m_hash_context); + } + + void md5_hash_provider_impl::write(const uint8_t* data, size_t count) + { + MD5_Update(&m_hash_context, data, count); + } + + void md5_hash_provider_impl::close() + { + m_hash.resize(MD5_DIGEST_LENGTH); + MD5_Final(m_hash.data(), &m_hash_context); + } + +#endif + +}}} // namespace azure::storage::core + diff --git a/Microsoft.WindowsAzure.Storage/src/logging.cpp b/Microsoft.WindowsAzure.Storage/src/logging.cpp new file mode 100644 index 00000000..7541a009 --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/src/logging.cpp @@ -0,0 +1,164 @@ +// ----------------------------------------------------------------------------------------- +// +// 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" + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +namespace azure { namespace storage { namespace core { + +#ifdef WIN32 + const std::wstring wconnector(L" : "); + + // {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) + { + log(context, level, utility::conversions::to_utf16string(message)); + } + } + + void logger::log(azure::storage::operation_context context, client_log_level level, const std::wstring& message) const + { + if (g_event_provider_handle != NULL) + { + utf16string utf16_message; + utf16string req_id_16 = utility::conversions::to_utf16string(context.client_request_id()); + + utf16_message.reserve(req_id_16.length() + wconnector.length() + message.length()); + utf16_message.append(req_id_16); + utf16_message.append(wconnector); + utf16_message.append(message); + + EventWriteString(g_event_provider_handle, get_etw_log_level(level), 0, utf16_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()); + } + +#else + + const std::string connector(" : "); + + logger::logger() + { + } + + logger::~logger() + { + } + + boost::log::trivial::severity_level get_boost_log_level(client_log_level level) + { + switch (level) + { + case client_log_level::log_level_error: + return boost::log::trivial::severity_level::error; + + case client_log_level::log_level_warning: + return boost::log::trivial::warning; + + case client_log_level::log_level_informational: + return boost::log::trivial::info; + + case client_log_level::log_level_verbose: + return boost::log::trivial::trace; + } + + throw std::invalid_argument("level"); + } + + void logger::log(azure::storage::operation_context context, client_log_level level, const std::string& message) const + { + std::string utf8_message; + utf8_message.reserve(context.client_request_id().length() + connector.length() + message.length()); + utf8_message.append(context.client_request_id()); + utf8_message.append(connector); + utf8_message.append(message); + + BOOST_LOG_SEV(context.logger(), get_boost_log_level(level)) << utf8_message; + } + + bool logger::should_log(azure::storage::operation_context context, client_log_level level) const + { + return (level != client_log_level::log_level_off) && (level <= context.log_level()); + } + +#endif // WIN32 + + logger logger::m_instance; + +}}} // namespace azure::storage::core + diff --git a/Microsoft.WindowsAzure.Storage/src/protocol_xml.cpp b/Microsoft.WindowsAzure.Storage/src/protocol_xml.cpp index 872f5080..ac39081f 100644 --- a/Microsoft.WindowsAzure.Storage/src/protocol_xml.cpp +++ b/Microsoft.WindowsAzure.Storage/src/protocol_xml.cpp @@ -114,13 +114,13 @@ namespace azure { namespace storage { namespace protocol { { if (element_name == xml_container && get_parent_element_name() == xml_containers) { - cloud_metadata metadata; - metadata.swap(m_metadata); - // End of the data for a Container. Create an item and add it to the list - m_items.push_back(cloud_blob_container_list_item(std::move(m_uri), std::move(m_name), std::move(metadata), std::move(m_properties))); + m_items.push_back(cloud_blob_container_list_item(std::move(m_uri), std::move(m_name), std::move(m_metadata), std::move(m_properties))); - m_properties = cloud_blob_container_properties(); + m_uri = web::uri(); + m_name = utility::string_t(); + m_metadata = azure::storage::cloud_metadata(); + m_properties = azure::storage::cloud_blob_container_properties(); } } @@ -305,20 +305,22 @@ namespace azure { namespace storage { namespace protocol { { if (get_parent_element_name() == xml_blobs) { - cloud_metadata metadata; - metadata.swap(m_metadata); - if (element_name == xml_blob) { - m_blob_items.push_back(cloud_blob_list_item(std::move(m_uri), std::move(m_name), std::move(m_snapshot_time), std::move(metadata), std::move(m_properties), std::move(m_copy_state))); + m_blob_items.push_back(cloud_blob_list_item(std::move(m_uri), std::move(m_name), std::move(m_snapshot_time), std::move(m_metadata), std::move(m_properties), std::move(m_copy_state))); + m_uri = web::uri(); + m_name = utility::string_t(); + m_snapshot_time = utility::string_t(); + m_metadata = azure::storage::cloud_metadata(); + m_properties = azure::storage::cloud_blob_properties(); + m_copy_state = azure::storage::copy_state(); } else if (element_name == xml_blob_prefix) { m_blob_prefix_items.push_back(cloud_blob_prefix_list_item(std::move(m_uri), std::move(m_name))); + m_uri = web::uri(); + m_name = utility::string_t(); } - - m_properties = cloud_blob_properties(); - m_snapshot_time = utility::string_t(); } } @@ -336,15 +338,16 @@ namespace azure { namespace storage { namespace protocol { void page_list_reader::handle_end_element(const utility::string_t& element_name) { - if (m_start != -1 && m_end != -1) + if (element_name == xml_page_range) { - if (element_name == xml_page_range) + if (m_start != -1 && m_end != -1) { page_range range(m_start, m_end); m_page_list.push_back(range); - m_start = -1; - m_end = -1; } + + m_start = -1; + m_end = -1; } } @@ -358,11 +361,6 @@ namespace azure { namespace storage { namespace protocol { { m_handling_what = 2; } - else if (m_handling_what != 0 && element_name == xml_block) - { - m_size = std::numeric_limits::max(); - m_name.clear(); - } } void block_list_reader::handle_element(const utility::string_t& element_name) @@ -392,8 +390,11 @@ namespace azure { namespace storage { namespace protocol { { if (!m_name.empty() && (m_size != std::numeric_limits::max())) { - m_block_list.push_back(block_list_item(m_name, m_size, m_handling_what == 1)); + m_block_list.push_back(block_list_item(std::move(m_name), m_size, m_handling_what == 1)); } + + m_size = std::numeric_limits::max(); + m_name = utility::string_t(); } } } @@ -560,16 +561,6 @@ namespace azure { namespace storage { namespace protocol { return outstream.str(); } - void list_queues_reader::handle_begin_element(const utility::string_t& element_name) - { - if (element_name == U("Queues")) - { - m_name.clear(); - //m_uri = web::http::uri(); - m_metadata.clear(); - } - } - void list_queues_reader::handle_element(const utility::string_t& element_name) { if (element_name == xml_name) @@ -595,25 +586,10 @@ namespace azure { namespace storage { namespace protocol { { if (element_name == U("Queue") && get_parent_element_name() == U("Queues")) { - cloud_metadata metadata; - metadata.swap(m_metadata); - //cloud_queue_list_item item(std::move(m_name), std::move(m_uri), std::move(metadata)); - cloud_queue_list_item item(std::move(m_name), std::move(metadata)); + cloud_queue_list_item item(std::move(m_name), std::move(m_metadata)); m_items.push_back(item); - } - } - - void message_reader::handle_begin_element(const utility::string_t& element_name) - { - if (element_name == U("QueueMessage")) - { - m_content.clear(); - m_id.clear(); - m_pop_receipt.clear(); - m_insertion_time = utility::datetime(); - m_expiration_time = utility::datetime(); - m_next_visible_time = utility::datetime(); - m_dequeue_count = 0; + m_name = utility::string_t(); + m_metadata = cloud_metadata(); } } @@ -621,7 +597,7 @@ namespace azure { namespace storage { namespace protocol { { if (element_name == U("MessageText")) { - m_content = get_current_element_text(); + m_content = get_current_element_text(); } else if (element_name == U("MessageId")) { @@ -656,6 +632,13 @@ namespace azure { namespace storage { namespace protocol { { cloud_message_list_item item(std::move(m_content), std::move(m_id), std::move(m_pop_receipt), m_insertion_time, m_expiration_time, m_next_visible_time, m_dequeue_count); m_items.push_back(item); + m_content = utility::string_t(); + m_id = utility::string_t(); + m_pop_receipt = utility::string_t(); + m_insertion_time = utility::datetime(); + m_expiration_time = utility::datetime(); + m_next_visible_time = utility::datetime(); + m_dequeue_count = 0; } } @@ -735,7 +718,12 @@ namespace azure { namespace storage { namespace protocol { { write_element(xml_service_properties_version, metrics.version()); write_element(xml_service_properties_enabled, metrics.enabled() ? header_value_true : header_value_false); - write_element(xml_service_properties_include_apis, metrics.include_apis() ? header_value_true : header_value_false); + + if (metrics.enabled()) + { + write_element(xml_service_properties_include_apis, metrics.include_apis() ? header_value_true : header_value_false); + } + write_retention_policy(metrics.retention_policy_enabled(), metrics.retention_days()); } diff --git a/Microsoft.WindowsAzure.Storage/src/request_factory.cpp b/Microsoft.WindowsAzure.Storage/src/request_factory.cpp index 02552f36..1195db10 100644 --- a/Microsoft.WindowsAzure.Storage/src/request_factory.cpp +++ b/Microsoft.WindowsAzure.Storage/src/request_factory.cpp @@ -23,6 +23,7 @@ namespace azure { namespace storage { namespace protocol { web::http::http_request base_request(web::http::method method, web::http::uri_builder uri_builder, const std::chrono::seconds& timeout, operation_context context) { + UNREFERENCED_PARAMETER(context); if (timeout.count() > 0) { uri_builder.append_query(core::make_query_parameter(uri_query_timeout, timeout.count(), /* do_encoding */ false)); diff --git a/Microsoft.WindowsAzure.Storage/src/request_result.cpp b/Microsoft.WindowsAzure.Storage/src/request_result.cpp index 8fe3a723..0801cf4c 100644 --- a/Microsoft.WindowsAzure.Storage/src/request_result.cpp +++ b/Microsoft.WindowsAzure.Storage/src/request_result.cpp @@ -28,7 +28,8 @@ namespace azure { namespace storage { m_start_time(start_time), m_target_location(target_location), m_end_time(utility::datetime::utc_now()), - m_http_status_code(response.status_code()) + m_http_status_code(response.status_code()), + m_content_length(-1) { parse_headers(response.headers()); if (parse_body_as_error) @@ -43,7 +44,8 @@ namespace azure { namespace storage { m_target_location(target_location), m_end_time(utility::datetime::utc_now()), m_http_status_code(http_status_code), - m_extended_error(std::move(extended_error)) + m_extended_error(std::move(extended_error)), + m_content_length(-1) { parse_headers(response.headers()); } @@ -51,6 +53,7 @@ namespace azure { namespace storage { void request_result::parse_headers(const web::http::http_headers& headers) { headers.match(protocol::ms_header_request_id, m_service_request_id); + headers.match(web::http::header_names::content_length, m_content_length); headers.match(web::http::header_names::content_md5, m_content_md5); headers.match(web::http::header_names::etag, m_etag); diff --git a/Microsoft.WindowsAzure.Storage/src/response_parsers.cpp b/Microsoft.WindowsAzure.Storage/src/response_parsers.cpp index f140caf9..f8eb2b36 100644 --- a/Microsoft.WindowsAzure.Storage/src/response_parsers.cpp +++ b/Microsoft.WindowsAzure.Storage/src/response_parsers.cpp @@ -24,22 +24,9 @@ namespace azure { namespace storage { namespace protocol { - void preprocess_response(const web::http::http_response& response, operation_context context) + void preprocess_response_void(const web::http::http_response& response, const request_result& result, operation_context context) { - preprocess_response(0, response, context); - } - - void check_stream_length_and_md5(utility::size64_t length, const utility::string_t& content_md5, const core::ostream_descriptor& descriptor) - { - if (length != descriptor.length()) - { - throw storage_exception(protocol::error_incorrect_length); - } - - if (!content_md5.empty() && !descriptor.content_md5().empty() && (content_md5 != descriptor.content_md5())) - { - throw storage_exception(protocol::error_md5_mismatch); - } + preprocess_response(0, response, result, context); } utility::string_t get_header_value(const web::http::http_headers& headers, const utility::string_t& header) @@ -252,8 +239,8 @@ namespace azure { namespace storage { namespace protocol { concurrency::streams::istream body_stream = response.body(); protocol::storage_error_reader reader(body_stream); - error_code = reader.extract_error_code(); - error_message = reader.extract_error_message(); + error_code = reader.move_error_code(); + error_message = reader.move_error_message(); return storage_extended_error(std::move(error_code), std::move(error_message), std::move(details)); } diff --git a/Microsoft.WindowsAzure.Storage/src/retry_policies.cpp b/Microsoft.WindowsAzure.Storage/src/retry_policies.cpp index d7594dd6..d5d2b948 100644 --- a/Microsoft.WindowsAzure.Storage/src/retry_policies.cpp +++ b/Microsoft.WindowsAzure.Storage/src/retry_policies.cpp @@ -41,6 +41,7 @@ namespace azure { namespace storage { retry_info basic_common_retry_policy::evaluate(const retry_context& retry_context, operation_context context) { + UNREFERENCED_PARAMETER(context); if (retry_context.current_retry_count() >= m_max_attempts) { return retry_info(); diff --git a/Microsoft.WindowsAzure.Storage/src/shared_access_signature.cpp b/Microsoft.WindowsAzure.Storage/src/shared_access_signature.cpp index 4f3f4418..8ba5bdc6 100644 --- a/Microsoft.WindowsAzure.Storage/src/shared_access_signature.cpp +++ b/Microsoft.WindowsAzure.Storage/src/shared_access_signature.cpp @@ -22,6 +22,7 @@ #include "was/queue.h" #include "was/table.h" #include "wascore/util.h" +#include "wascore/resources.h" namespace azure { namespace storage { namespace protocol { @@ -58,16 +59,14 @@ namespace azure { namespace storage { namespace protocol { return builder; } - utility::ostringstream_t get_sas_string_to_sign(const utility::string_t& identifier, const shared_access_policy& policy, const utility::string_t& resource) + void get_sas_string_to_sign(utility::ostringstream_t& str, const utility::string_t& identifier, const shared_access_policy& policy, const utility::string_t& resource) { - utility::ostringstream_t str; str << policy.permissions_to_string() << U('\n'); str << convert_datetime_if_initialized(policy.start()) << U('\n'); str << convert_datetime_if_initialized(policy.expiry()) << U('\n'); str << resource << U('\n'); str << identifier << U('\n'); str << header_value_storage_version; - return str; } storage_credentials parse_query(const web::http::uri& uri, bool require_signed_resource) @@ -94,7 +93,7 @@ namespace azure { namespace storage { namespace protocol { protocol::uri_query_sas_signature, }; - const int sas_parameters_size = sizeof(sas_parameters) / sizeof(sas_parameters[0]); + const int sas_parameters_size = (int) (sizeof(sas_parameters) / sizeof(sas_parameters[0])); auto splitted_query = web::http::uri::split_query(uri.query()); @@ -131,8 +130,8 @@ namespace azure { namespace storage { namespace protocol { utility::string_t get_blob_sas_string_to_sign(const utility::string_t& identifier, const shared_access_policy& policy, const cloud_blob_shared_access_headers& headers, const utility::string_t& resource, const storage_credentials& credentials) { - auto str = get_sas_string_to_sign(identifier, policy, resource); - + utility::ostringstream_t str; + get_sas_string_to_sign(str, identifier, policy, resource); str << U('\n') << headers.cache_control(); str << U('\n') << headers.content_disposition(); str << U('\n') << headers.content_encoding(); @@ -163,7 +162,8 @@ namespace azure { namespace storage { namespace protocol { utility::string_t get_queue_sas_string_to_sign(const utility::string_t& identifier, const shared_access_policy& policy, const utility::string_t& resource, const storage_credentials& credentials) { - auto str = get_sas_string_to_sign(identifier, policy, resource); + utility::ostringstream_t str; + get_sas_string_to_sign(str, identifier, policy, resource); return calculate_hmac_sha256_hash(str.str(), credentials); } @@ -182,7 +182,8 @@ namespace azure { namespace storage { namespace protocol { utility::string_t get_table_sas_string_to_sign(const utility::string_t& identifier, const shared_access_policy& policy, const utility::string_t& start_partition_key, const utility::string_t& start_row_key, const utility::string_t& end_partition_key, const utility::string_t& end_row_key, const utility::string_t& resource, const storage_credentials& credentials) { - auto str = get_sas_string_to_sign(identifier, policy, resource); + utility::ostringstream_t str; + get_sas_string_to_sign(str, identifier, policy, resource); str << U('\n') << start_partition_key; str << U('\n') << start_row_key; diff --git a/Microsoft.WindowsAzure.Storage/src/table_response_parsers.cpp b/Microsoft.WindowsAzure.Storage/src/table_response_parsers.cpp index 2402eaae..c4203bc5 100644 --- a/Microsoft.WindowsAzure.Storage/src/table_response_parsers.cpp +++ b/Microsoft.WindowsAzure.Storage/src/table_response_parsers.cpp @@ -143,7 +143,7 @@ namespace azure { namespace storage { namespace protocol { web::json::value document = web::json::value::parse(utility::conversions::to_string_t(error_string)); storage_extended_error extended_error = protocol::parse_table_error(document); - request_result request_result(utility::datetime(), storage_location::unspecified, response, status_code, extended_error); + request_result request_result(utility::datetime(), storage_location::unspecified, response, (web::http::status_code) status_code, extended_error); throw storage_exception(status_message, request_result); } } @@ -220,7 +220,7 @@ namespace azure { namespace storage { namespace protocol { web::json::value document = web::json::value::parse(utility::conversions::to_string_t(error_string)); storage_extended_error extended_error = protocol::parse_table_error(document); - request_result request_result(utility::datetime(), storage_location::unspecified, response, status_code, extended_error); + request_result request_result(utility::datetime(), storage_location::unspecified, response, (web::http::status_code) status_code, extended_error); throw storage_exception(status_message, request_result); } } diff --git a/Microsoft.WindowsAzure.Storage/src/util.cpp b/Microsoft.WindowsAzure.Storage/src/util.cpp index b3f4ace5..a22e8282 100644 --- a/Microsoft.WindowsAzure.Storage/src/util.cpp +++ b/Microsoft.WindowsAzure.Storage/src/util.cpp @@ -22,12 +22,19 @@ #include "wascore/resources.h" #ifdef WIN32 +#define WIN32_LEAN_AND_MEAN #include +#include +#include +#include +#else +#include +#include #endif namespace azure { namespace storage { namespace core { - const wchar_t hex_alphabet[16] = {U('0'), U('1'), U('2'), U('3'), U('4'), U('5'), U('6'), U('7'), U('8'), U('9'), U('a'), U('b'), U('c'), U('d'), U('e'), U('f')}; + const utility::char_t hex_alphabet[16] = {U('0'), U('1'), U('2'), U('3'), U('4'), U('5'), U('6'), U('7'), U('8'), U('9'), U('a'), U('b'), U('c'), U('d'), U('e'), U('f')}; const utility::datetime::interval_type second_interval = 10000000; utility::string_t make_query_parameter_impl(const utility::string_t& parameter_name, const utility::string_t& parameter_value) @@ -340,13 +347,83 @@ namespace azure { namespace storage { namespace core { } else { - strftime(output, sizeof(output), - format == RFC_1123 ? "%a, %d %b %Y %H:%M:%S GMT" : "%Y-%m-%dT%H:%M:%SZ", - &datetime); + strftime(output, sizeof(output), "%Y-%m-%dT%H:%M:%SZ", &datetime); } return std::string(output); #endif } +#ifdef WIN32 + class delay_event + { + public: + delay_event(std::chrono::milliseconds timeout) + : m_callback(new concurrency::call(std::function(std::bind(&delay_event::timer_fired, this, std::placeholders::_1)))), m_timer(static_cast(timeout.count()), 0, m_callback, false) + { + } + + ~delay_event() + { + delete m_callback; + } + + void start() + { + m_timer.start(); + } + + pplx::task create_task() + { + return pplx::task(m_completion_event); + } + + private: + concurrency::call* m_callback; + pplx::task_completion_event m_completion_event; + concurrency::timer m_timer; + + void timer_fired(const int& dummy) + { + UNREFERENCED_PARAMETER(dummy); + + m_completion_event.set(); + } + }; +#else + class delay_event + { + public: + delay_event(std::chrono::milliseconds timeout) + : m_timeout(timeout) + { + } + + void start() + { + // TODO: Consider using boost::asio::deadline_timer and implementing a threadpool + std::this_thread::sleep_for(m_timeout); + } + + pplx::task create_task() + { + return pplx::task_from_result(); + } + + private: + std::chrono::milliseconds m_timeout; + }; +#endif + + pplx::task complete_after(std::chrono::milliseconds timeout) + { + delay_event* event = new delay_event(timeout); + event->start(); + + return event->create_task().then([event]() + { + delete event; + }); + } + }}} // namespace azure::storage::core diff --git a/Microsoft.WindowsAzure.Storage/src/xmlhelpers.cpp b/Microsoft.WindowsAzure.Storage/src/xmlhelpers.cpp index 8626451e..9e43d9f9 100644 --- a/Microsoft.WindowsAzure.Storage/src/xmlhelpers.cpp +++ b/Microsoft.WindowsAzure.Storage/src/xmlhelpers.cpp @@ -467,7 +467,7 @@ namespace azure { namespace storage { namespace core { namespace xml { throw utility::details::create_system_error(error); } #else - UNUSED_PARAMETER(namespaceUri); + UNREFERENCED_PARAMETER(namespaceUri); if (prefix == U("xmlns")) { m_elementStack.top()->set_namespace_declaration( diff --git a/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt b/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt new file mode 100644 index 00000000..bbe779af --- /dev/null +++ b/Microsoft.WindowsAzure.Storage/tests/CMakeLists.txt @@ -0,0 +1,97 @@ +include_directories(../includes ${CASABLANCA_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${LibXML++_INCLUDE_DIRS} UnitTest++/src) + +# THE ORDER OF FILES IS VERY /VERY/ IMPORTANT +if(UNIX) + set(SOURCES + blob_lease_test.cpp + blob_streams_test.cpp + blob_test_base.cpp + cloud_blob_client_test.cpp + cloud_blob_container_test.cpp + cloud_blob_directory_test.cpp + cloud_blob_test.cpp + cloud_block_blob_test.cpp + cloud_page_blob_test.cpp + cloud_queue_client_test.cpp + cloud_queue_test.cpp + cloud_storage_account_test.cpp + cloud_table_client_test.cpp + cloud_table_test.cpp + executor_test.cpp + main.cpp + read_from_secondary_test.cpp + retry_policy_test.cpp + service_properties_test.cpp + stdafx.cpp + test_base.cpp + test_helper.cpp + ) + if(APPLE) + # set(SOURCES ${SOURCES} apple.cpp) + find_library(COREFOUNDATION CoreFoundation "/") + set(EXTRALINKS ${COREFOUNDATION}) + else() + # set(SOURCES ${SOURCES} linux.cpp) + endif() +elseif(WIN32) + set(SOURCES + blob_lease_test.cpp + blob_streams_test.cpp + blob_test_base.cpp + cloud_blob_client_test.cpp + cloud_blob_container_test.cpp + cloud_blob_directory_test.cpp + cloud_blob_test.cpp + cloud_block_blob_test.cpp + cloud_page_blob_test.cpp + cloud_queue_client_test.cpp + cloud_queue_test.cpp + cloud_storage_account_test.cpp + cloud_table_client_test.cpp + cloud_table_test.cpp + executor_test.cpp + main.cpp + read_from_secondary_test.cpp + retry_policy_test.cpp + service_properties_test.cpp + stdafx.cpp + test_base.cpp + test_helper.cpp + ) + add_definitions( + -D_ASYNCRT_EXPORT + -DAZURESTORAGESERVICES_EXPORTS + -D_PPLX_EXPORT + -DWIN32 + -D_MBCS + -D_USRDLL + ) + set(EXTRALINKS Httpapi.lib Winhttp.dll) +endif() + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} -Werror -pedantic") + +add_executable(${AZURESTORAGE_LIBRARY_TEST} ${SOURCES}) + +target_link_libraries(${AZURESTORAGE_LIBRARY_TEST} + ${AZURESTORAGE_LIBRARY} + ${UNITTEST_LIBRARY} + ${UUID_LIBRARY} + ${CMAKE_THREAD_LIBS_INIT} + ${CASABLANCA_LIBRARY} + ${Boost_LIBRARIES} + ${Boost_FRAMEWORK} + ${LibXML++_LIBRARIES} + ${COREFOUNDATION} + ${EXTRALINKS} + ) + +# Portions specific to cpprest binary versioning. +if(WIN32) + set_target_properties(${AZURESTORAGE_LIBRARY_TEST} PROPERTIES + OUTPUT_NAME "${AZURESTORAGE_LIBRARY_TEST}") +else() + set_target_properties(${AZURESTORAGE_LIBRARY_TEST} PROPERTIES + SOVERSION ${AZURESTORAGE_VERSION_MAJOR}.${AZURESTORAGE_VERSION_MINOR}) +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 2c7b4b80..eaed55b2 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.v120.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -100,7 +101,7 @@ - + @@ -152,7 +153,11 @@ - + + + + + \ No newline at end of file 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 e0c2a096..bb50afff 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 @@ -50,7 +50,7 @@ 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 dd13b252..370c56fb 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj @@ -1,6 +1,7 @@  - + + Debug @@ -100,7 +101,7 @@ - + @@ -152,7 +153,11 @@ + + + + + - \ No newline at end of file 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 e0c2a096..bb50afff 100644 --- a/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj.filters +++ b/Microsoft.WindowsAzure.Storage/tests/Microsoft.WindowsAzure.Storage.UnitTests.vcxproj.filters @@ -50,7 +50,7 @@ Source Files - + Source Files diff --git a/Microsoft.WindowsAzure.Storage/tests/README.md b/Microsoft.WindowsAzure.Storage/tests/README.md index b0ddb33f..608c38e3 100644 --- a/Microsoft.WindowsAzure.Storage/tests/README.md +++ b/Microsoft.WindowsAzure.Storage/tests/README.md @@ -1,3 +1,3 @@ -# Unit Tests for Windows Azure Storage Client Library for C++ +# 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. diff --git a/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp b/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp index cd7d553c..74639c29 100644 --- a/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/blob_streams_test.cpp @@ -26,7 +26,7 @@ size_t seek_read_and_compare(concurrency::streams::istream stream, std::vector> downloaded_blob; m_blob.download_to_stream(downloaded_blob.create_ostream(), azure::storage::access_condition(), options, m_context); - CHECK_ARRAY_EQUAL(final_blob_contents, downloaded_blob.collection(), final_blob_contents.size()); + CHECK_ARRAY_EQUAL(final_blob_contents, downloaded_blob.collection(), (int)final_blob_contents.size()); } TEST_FIXTURE(page_blob_test_base, existing_page_blob_write_stream) @@ -243,7 +243,7 @@ SUITE(Blob) CHECK_ARRAY_EQUAL(buffer.data(), downloaded_blob.collection().data(), 512); CHECK_ARRAY_EQUAL(buffer.data(), downloaded_blob.collection().data() + 512, 512); - CHECK_ARRAY_EQUAL(buffer.data() + 1024, downloaded_blob.collection().data() + 1024, buffer.size() - 1024); + CHECK_ARRAY_EQUAL(buffer.data() + 1024, downloaded_blob.collection().data() + 1024, (int)(buffer.size()) - 1024); } TEST_FIXTURE(block_blob_test_base, block_blob_write_stream_access_condition) diff --git a/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp b/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp index a47b6ef4..f5b41b98 100644 --- a/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/blob_test_base.cpp @@ -30,13 +30,13 @@ utility::string_t blob_service_test_base::fill_buffer_and_get_md5(std::vector uint8_t { - return std::rand() % UINT8_MAX; + return (uint8_t)(std::rand() % (int)UINT8_MAX); }); - azure::storage::core::hash_md5_streambuf md5; - md5.putn(buffer.data() + offset, count).wait(); - md5.close().wait(); - return utility::conversions::to_base64(md5.hash()); + azure::storage::core::hash_provider provider = azure::storage::core::hash_provider::create_md5_hash_provider(); + provider.write(buffer.data() + offset, count); + provider.close(); + return provider.hash(); } utility::string_t blob_service_test_base::get_random_container_name(size_t length) diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp index 3ba62e07..bbcf47f6 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_client_test.cpp @@ -67,6 +67,24 @@ std::vector blob_service_test_base::list_all_blobs_f SUITE(Blob) { + TEST_FIXTURE(blob_service_test_base, get_container_reference) + { + utility::string_t container_name = get_random_container_name(); + azure::storage::cloud_blob_container container = m_client.get_container_reference(container_name); + + CHECK(!container.service_client().base_uri().primary_uri().is_empty()); + CHECK(container.service_client().credentials().is_shared_key()); + CHECK(container.name() == container_name); + CHECK(!container.uri().primary_uri().is_empty()); + CHECK(container.metadata().empty()); + CHECK(container.properties().etag().empty()); + CHECK(!container.properties().last_modified().is_initialized()); + CHECK(container.properties().lease_status() == azure::storage::lease_status::unspecified); + CHECK(container.properties().lease_state() == azure::storage::lease_state::unspecified); + CHECK(container.properties().lease_duration() == azure::storage::lease_duration::unspecified); + CHECK(container.is_valid()); + } + TEST_FIXTURE(blob_service_test_base_with_objects_to_delete, list_containers_with_prefix) { auto prefix = get_random_container_name(); @@ -120,7 +138,7 @@ SUITE(Blob) std::vector containers(m_containers_to_delete); - auto listing = list_all_containers(utility::string_t(), azure::storage::container_listing_details::all, 1, azure::storage::blob_request_options()); + auto listing = list_all_containers(utility::string_t(), azure::storage::container_listing_details::all, 5000, azure::storage::blob_request_options()); for (auto listing_iter = listing.begin(); listing_iter != listing.end(); ++listing_iter) { for (auto iter = containers.begin(); iter != containers.end(); ++iter) diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp index 264d8a6c..950d3287 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_blob_test.cpp @@ -99,7 +99,7 @@ azure::storage::operation_context blob_test_base::upload_and_download(azure::sto concurrency::streams::container_buffer> output_buffer; blob.download_to_stream(output_buffer.create_ostream(), azure::storage::access_condition(), download_options, context); - CHECK_ARRAY_EQUAL(buffer.data() + buffer_offset, output_buffer.collection().data(), blob_size == 0 ? (buffer_size - buffer_offset) : blob_size); + CHECK_ARRAY_EQUAL(buffer.data() + buffer_offset, output_buffer.collection().data(),(int) (blob_size == 0 ? (buffer_size - buffer_offset) : blob_size)); context.set_sending_request(std::function()); return context; @@ -239,7 +239,7 @@ SUITE(Blob) blob.create(1024, azure::storage::access_condition(), options, m_context); CHECK_EQUAL(1024, blob.properties().size()); CHECK(!blob.properties().etag().empty()); - CHECK((utility::datetime::utc_now() - blob.properties().last_modified()) < utility::datetime::from_minutes(5)); + CHECK((utility::datetime::utc_now() - blob.properties().last_modified()) < (int64_t)utility::datetime::from_minutes(5)); CHECK(blob.properties().cache_control().empty()); CHECK(blob.properties().content_disposition().empty()); CHECK(blob.properties().content_encoding().empty()); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp index a9f8f521..f53232b0 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_block_blob_test.cpp @@ -87,7 +87,7 @@ SUITE(Blob) }); options.set_use_transactional_md5(false); - for (int i = 0; i < 3; ++i) + for (uint16_t i = 0; i < 3; ++i) { fill_buffer_and_get_md5(buffer); auto stream = concurrency::streams::bytestream::open_istream(buffer); @@ -103,7 +103,7 @@ SUITE(Blob) uncommitted_blocks.clear(); options.set_use_transactional_md5(false); - for (int i = 3; i < 6; ++i) + for (uint16_t i = 3; i < 6; ++i) { auto md5 = fill_buffer_and_get_md5(buffer); auto stream = concurrency::streams::bytestream::open_istream(buffer); @@ -119,7 +119,7 @@ SUITE(Blob) uncommitted_blocks.clear(); options.set_use_transactional_md5(true); - for (int i = 6; i < 9; ++i) + for (uint16_t i = 6; i < 9; ++i) { auto md5 = fill_buffer_and_get_md5(buffer); auto stream = concurrency::streams::bytestream::open_istream(buffer); @@ -193,6 +193,55 @@ SUITE(Blob) check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 7, true), 6); m_blob.delete_blob(); m_blob.properties().set_content_md5(utility::string_t()); + + options.set_store_blob_content_md5(false); + options.set_use_transactional_md5(false); + options.set_parallelism_factor(1); + options.set_http_buffer_size(512 * 1024); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 1, false), 1); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_stream_write_size_in_bytes(4 * 1024 * 1024); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 1, false), 1); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_store_blob_content_md5(true); + options.set_single_blob_upload_threshold_in_bytes(32 * 1024 * 1024); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 1, true), 1); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_parallelism_factor(4); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 3, true), 2); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_store_blob_content_md5(false); + options.set_parallelism_factor(1); + options.set_stream_write_size_in_bytes(1 * 1024 * 1024); + options.set_single_blob_upload_threshold_in_bytes(6 * 1024 * 1024); + options.set_http_buffer_size(0); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 1, false), 1); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_stream_write_size_in_bytes(4 * 1024 * 1024); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 1, false), 1); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_store_blob_content_md5(true); + options.set_single_blob_upload_threshold_in_bytes(32 * 1024 * 1024); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 1, true), 1); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); + + options.set_parallelism_factor(4); + check_parallelism(upload_and_download(m_blob, size, 0, 0, true, options, 3, true), 2); + m_blob.delete_blob(); + m_blob.properties().set_content_md5(utility::string_t()); } TEST_FIXTURE(block_blob_test_base, block_blob_upload_with_nonseekable) @@ -324,9 +373,9 @@ SUITE(Blob) const size_t buffer_size = 2 * 1024 * 1024; azure::storage::blob_request_options options; options.set_store_blob_content_md5(false); - CHECK_THROW(upload_and_download(m_blob, buffer_size, 0, buffer_size + 1, true, options, 0, false), azure::storage::storage_exception); + CHECK_THROW(upload_and_download(m_blob, buffer_size, 0, buffer_size + 1, true, options, 0, false), std::invalid_argument); CHECK_THROW(upload_and_download(m_blob, buffer_size, 0, buffer_size + 1, false, options, 0, false), std::invalid_argument); - CHECK_THROW(upload_and_download(m_blob, buffer_size, 1024, buffer_size - 1023, true, options, 0, false), azure::storage::storage_exception); + CHECK_THROW(upload_and_download(m_blob, buffer_size, 1024, buffer_size - 1023, true, options, 0, false), std::invalid_argument); CHECK_THROW(upload_and_download(m_blob, buffer_size, 1024, buffer_size - 1023, false, options, 0, false), std::invalid_argument); } @@ -383,7 +432,7 @@ SUITE(Blob) downloaded_file.close().wait(); CHECK_EQUAL(original_file_buffer.collection().size(), downloaded_file_buffer.collection().size()); - CHECK_ARRAY_EQUAL(original_file_buffer.collection(), downloaded_file_buffer.collection(), downloaded_file_buffer.collection().size()); + CHECK_ARRAY_EQUAL(original_file_buffer.collection(), downloaded_file_buffer.collection(), (int) downloaded_file_buffer.collection().size()); m_blob.properties().set_content_md5(dummy_md5); m_blob.upload_properties(); @@ -491,11 +540,10 @@ SUITE(Blob) m_blob.properties().set_content_type(U("text/plain; charset=utf-8")); std::vector blocks; - for (int i = 0; i < 10; i++) + for (uint16_t i = 0; i < 10; i++) { auto id = get_block_id(i); auto utf8_body = utility::conversions::to_utf8string(utility::conversions::print_string(i)); - auto length = utf8_body.size(); auto stream = concurrency::streams::bytestream::open_istream(std::move(utf8_body)); m_blob.upload_block(id, stream, utility::string_t(), azure::storage::access_condition(), azure::storage::blob_request_options(), m_context); blocks.push_back(azure::storage::block_list_item(id)); @@ -516,7 +564,6 @@ SUITE(Blob) auto id = get_block_id(4); auto utf8_body = utility::conversions::to_utf8string(utility::conversions::print_string(4)); - auto length = utf8_body.size(); auto stream = concurrency::streams::bytestream::open_istream(std::move(utf8_body)); m_blob.upload_block(id, stream, utility::string_t(), azure::storage::access_condition(), azure::storage::blob_request_options(), m_context); blocks.insert(blocks.begin(), azure::storage::block_list_item(id)); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp index 2f5188fa..710e45ec 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_page_blob_test.cpp @@ -361,7 +361,7 @@ SUITE(Blob) downloaded_file.close().wait(); CHECK_EQUAL(original_file_buffer.collection().size(), downloaded_file_buffer.collection().size()); - CHECK_ARRAY_EQUAL(original_file_buffer.collection(), downloaded_file_buffer.collection(), downloaded_file_buffer.collection().size()); + CHECK_ARRAY_EQUAL(original_file_buffer.collection(), downloaded_file_buffer.collection(), (int)downloaded_file_buffer.collection().size()); m_blob.properties().set_content_md5(dummy_md5); m_blob.upload_properties(); diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp index 14712720..d30392e1 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_queue_client_test.cpp @@ -142,6 +142,10 @@ SUITE(QueueClient) CHECK(context.request_results()[0].extended_error().code().empty()); CHECK(context.request_results()[0].extended_error().message().empty()); CHECK(context.request_results()[0].extended_error().details().empty()); + for (int i = 0; i < QUEUE_COUNT; ++i) + { + CHECK(is_found[i]); + } } { @@ -235,7 +239,6 @@ SUITE(QueueClient) result_segment = client.list_queues_segmented(prefix, get_metadata, max_results, token, options, context); std::vector results = result_segment.results(); - CHECK(results.size() >= 0); CHECK((int)results.size() <= max_results); for (std::vector::const_iterator itr = results.cbegin(); itr != results.cend(); ++itr) @@ -279,6 +282,10 @@ SUITE(QueueClient) while (!token.empty()); CHECK(segment_count > 1); + for (int i = 0; i < QUEUE_COUNT; ++i) + { + CHECK(is_found[i]); + } for (int i = 0; i < QUEUE_COUNT; ++i) { diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_queue_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_queue_test.cpp index 568e4c41..bef981a3 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_queue_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_queue_test.cpp @@ -158,7 +158,7 @@ SUITE(Queue) azure::storage::cloud_queue_message message(content); CHECK(message.content_as_string().size() >= content.size()); - CHECK_ARRAY_EQUAL(content, message.content_as_binary(), content.size()); + CHECK_ARRAY_EQUAL(content, message.content_as_binary(), (int)content.size()); CHECK(message.id().empty()); CHECK(message.pop_receipt().empty()); CHECK(!message.expiration_time().is_initialized()); @@ -170,7 +170,7 @@ SUITE(Queue) message.set_content(content); CHECK(message.content_as_string().size() >= content.size()); - CHECK_ARRAY_EQUAL(content, message.content_as_binary(), content.size()); + CHECK_ARRAY_EQUAL(content, message.content_as_binary(), (int)content.size()); CHECK(message.id().empty()); CHECK(message.pop_receipt().empty()); CHECK(!message.expiration_time().is_initialized()); @@ -1747,6 +1747,9 @@ SUITE(Queue) utility::string_t old_pop_recepit = message2.pop_receipt(); utility::datetime old_next_visible_time = message2.next_visibile_time(); + UNREFERENCED_PARAMETER(old_pop_recepit); + UNREFERENCED_PARAMETER(old_next_visible_time); + std::chrono::seconds visibility_timeout; bool update_content; azure::storage::queue_request_options options; diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp index 8fea37e7..33f9195e 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_table_client_test.cpp @@ -135,6 +135,10 @@ SUITE(TableClient) CHECK(context.request_results()[0].extended_error().code().empty()); CHECK(context.request_results()[0].extended_error().message().empty()); CHECK(context.request_results()[0].extended_error().details().empty()); + for (int i = 0; i < TABLE_COUNT; ++i) + { + CHECK(is_found[i]); + } for (int i = 0; i < TABLE_COUNT; ++i) { @@ -172,7 +176,6 @@ SUITE(TableClient) result_segment = client.list_tables_segmented(prefix, max_results, token, options, context); std::vector results = result_segment.results(); - CHECK(results.size() >= 0); CHECK((int)results.size() <= max_results); for (std::vector::const_iterator itr = results.cbegin(); itr != results.cend(); ++itr) @@ -216,6 +219,10 @@ SUITE(TableClient) while (!token.empty()); CHECK(segment_count > 1); + for (int i = 0; i < TABLE_COUNT; ++i) + { + CHECK(is_found[i]); + } for (int i = 0; i < TABLE_COUNT; ++i) { diff --git a/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp b/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp index 5c47e167..bc4b2c68 100644 --- a/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/cloud_table_test.cpp @@ -114,7 +114,7 @@ SUITE(Table) CHECK(property.property_type() == azure::storage::edm_type::binary); CHECK(!property.is_null()); - CHECK_ARRAY_EQUAL(value, property.binary_value(), value.size()); + CHECK_ARRAY_EQUAL(value, property.binary_value(), (int)value.size()); CHECK_THROW(property.boolean_value(), std::runtime_error); CHECK_THROW(property.datetime_value(), std::runtime_error); @@ -131,7 +131,7 @@ SUITE(Table) CHECK(property.property_type() == azure::storage::edm_type::binary); CHECK(!property.is_null()); - CHECK_ARRAY_EQUAL(value, property.binary_value(), value.size()); + CHECK_ARRAY_EQUAL(value, property.binary_value(), (int)value.size()); CHECK_THROW(property.boolean_value(), std::runtime_error); CHECK_THROW(property.datetime_value(), std::runtime_error); @@ -367,7 +367,7 @@ SUITE(Table) CHECK(property.property_type() == azure::storage::edm_type::guid); CHECK(!property.is_null()); - CHECK(property.guid_value() == value); + CHECK(utility::uuid_equal(property.guid_value(), value)); CHECK_THROW(property.binary_value(), std::runtime_error); CHECK_THROW(property.boolean_value(), std::runtime_error); @@ -384,7 +384,7 @@ SUITE(Table) CHECK(property.property_type() == azure::storage::edm_type::guid); CHECK(!property.is_null()); - CHECK(property.guid_value() == value); + CHECK(utility::uuid_equal(property.guid_value(), value)); CHECK_THROW(property.binary_value(), std::runtime_error); CHECK_THROW(property.boolean_value(), std::runtime_error); @@ -1395,7 +1395,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); @@ -1663,7 +1663,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); @@ -1767,7 +1767,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); CHECK(result.entity().properties().find(U("PropertyI")) != result.entity().properties().cend()); @@ -1875,7 +1875,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); CHECK(result.entity().properties().find(U("PropertyI")) != result.entity().properties().cend()); @@ -2088,7 +2088,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); @@ -2188,7 +2188,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); CHECK(result.entity().properties().find(U("PropertyI")) != result.entity().properties().cend()); @@ -2292,7 +2292,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); CHECK(result.entity().properties().find(U("PropertyK")) != result.entity().properties().cend()); @@ -2505,7 +2505,7 @@ SUITE(Table) CHECK(result.entity().properties().find(U("PropertyF")) != result.entity().properties().cend()); CHECK(result.entity().properties().find(U("PropertyF"))->second.datetime_value() == datetime_value); CHECK(result.entity().properties().find(U("PropertyG")) != result.entity().properties().cend()); - CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), binary_value.size()); + CHECK_ARRAY_EQUAL(binary_value, result.entity().properties().find(U("PropertyG"))->second.binary_value(), (int)binary_value.size()); CHECK(result.entity().properties().find(U("PropertyH")) != result.entity().properties().cend()); CHECK(utility::uuid_equal(result.entity().properties().find(U("PropertyH"))->second.guid_value(), guid_value)); @@ -3305,7 +3305,6 @@ SUITE(Table) azure::storage::cloud_table table = get_table(); utility::string_t partition_key = get_random_string(); - utility::string_t row_keys[BATCH_SIZE]; { azure::storage::table_batch_operation operation; @@ -3479,7 +3478,7 @@ SUITE(Table) for (int row2 = 0; row2 < 26; ++row2) { - utility::string_t row_key = get_string('a' + row1, 'a' + row2); + utility::string_t row_key = get_string((utility::char_t)('a' + row1), (utility::char_t)('a' + row2)); azure::storage::table_entity entity(partition_key, row_key); @@ -3513,6 +3512,19 @@ SUITE(Table) } } + utility::string_t uuid_string = U("12345678-abcd-efab-cdef-1234567890ab"); + utility::uuid uuid_to_use = utility::string_to_uuid(uuid_string); + utility::string_t converted_uuid_string = utility::uuid_to_string(uuid_to_use); + + // Explicit checks to ensure that UUIDs behave as we would expect per platform + // After this check, we can jsut use converted_uuid_string. +#ifdef WIN32 + CHECK(uuid_string.compare(converted_uuid_string) == 0); +#else + utility::string_t capital_uuid_string = U("12345678-ABCD-EFAB-CDEF-1234567890AB"); + CHECK((capital_uuid_string).compare(converted_uuid_string) == 0); +#endif // WIN32 + { azure::storage::table_query query; azure::storage::table_request_options options; @@ -3535,31 +3547,31 @@ SUITE(Table) azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::generate_filter_condition(U("PartitionKey"), azure::storage::query_comparison_operator::equal, partition_key1), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::greater_than_or_equal, U("k"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::less_than, U("n"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("Timestamp"), azure::storage::query_comparison_operator::greater_than_or_equal, utility::datetime::from_string(U("2013-09-01T00:00:00Z"), utility::datetime::ISO_8601))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyA"), azure::storage::query_comparison_operator::not_equal, false)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyB"), azure::storage::query_comparison_operator::not_equal, 1234567890)), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, 1234567890123456789LL)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, (int64_t)1234567890123456789LL)), + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyD"), azure::storage::query_comparison_operator::not_equal, 9.1234567890123456789)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyE"), azure::storage::query_comparison_operator::not_equal, U("ABCDE12345"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyF"), azure::storage::query_comparison_operator::not_equal, datetime_value)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyG"), azure::storage::query_comparison_operator::not_equal, std::vector(10, 'X'))), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, utility::string_to_uuid(U("12345678-abcd-efab-cdef-1234567890ab")))); + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, uuid_to_use)); query.set_filter_string(filter_string); - utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'12345678-abcd-efab-cdef-1234567890ab')")); + utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'") + converted_uuid_string + U("')")); CHECK(filter_string.compare(expected_filter_string) == 0); std::vector select_columns; @@ -3648,31 +3660,31 @@ SUITE(Table) azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::generate_filter_condition(U("PartitionKey"), azure::storage::query_comparison_operator::equal, partition_key1), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::greater_than_or_equal, U("k"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::less_than, U("n"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("Timestamp"), azure::storage::query_comparison_operator::greater_than_or_equal, utility::datetime::from_string(U("2013-09-01T00:00:00Z"), utility::datetime::ISO_8601))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyA"), azure::storage::query_comparison_operator::not_equal, false)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyB"), azure::storage::query_comparison_operator::not_equal, 1234567890)), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, 1234567890123456789LL)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, (int64_t)1234567890123456789LL)), + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyD"), azure::storage::query_comparison_operator::not_equal, 9.1234567890123456789)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyE"), azure::storage::query_comparison_operator::not_equal, U("ABCDE12345"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyF"), azure::storage::query_comparison_operator::not_equal, datetime_value)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyG"), azure::storage::query_comparison_operator::not_equal, std::vector(10, 'X'))), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, utility::string_to_uuid(U("12345678-abcd-efab-cdef-1234567890ab")))); + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, uuid_to_use)); query.set_filter_string(filter_string); - utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'12345678-abcd-efab-cdef-1234567890ab')")); + utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'") + converted_uuid_string + U("')")); CHECK(filter_string.compare(expected_filter_string) == 0); std::vector select_columns; @@ -3762,7 +3774,7 @@ SUITE(Table) for (int row2 = 0; row2 < 26; ++row2) { - utility::string_t row_key = get_string('a' + row1, 'a' + row2); + utility::string_t row_key = get_string((utility::char_t)('a' + row1), (utility::char_t)('a' + row2)); azure::storage::table_entity entity(partition_key, row_key); @@ -3796,6 +3808,10 @@ SUITE(Table) } } + utility::string_t uuid_string = U("12345678-abcd-efab-cdef-1234567890ab"); + utility::uuid uuid_to_use = utility::string_to_uuid(uuid_string); + utility::string_t converted_uuid_string = utility::uuid_to_string(uuid_to_use); + { azure::storage::table_query query; azure::storage::table_request_options options; @@ -3818,31 +3834,31 @@ SUITE(Table) azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::generate_filter_condition(U("PartitionKey"), azure::storage::query_comparison_operator::equal, partition_key1), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::greater_than_or_equal, U("k"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::less_than, U("n"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("Timestamp"), azure::storage::query_comparison_operator::greater_than_or_equal, utility::datetime::from_string(U("2013-09-01T00:00:00Z"), utility::datetime::ISO_8601))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyA"), azure::storage::query_comparison_operator::not_equal, false)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyB"), azure::storage::query_comparison_operator::not_equal, 1234567890)), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, 1234567890123456789LL)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, (int64_t)1234567890123456789LL)), + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyD"), azure::storage::query_comparison_operator::not_equal, 9.1234567890123456789)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyE"), azure::storage::query_comparison_operator::not_equal, U("ABCDE12345"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyF"), azure::storage::query_comparison_operator::not_equal, datetime_value)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyG"), azure::storage::query_comparison_operator::not_equal, std::vector(10, 'X'))), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, utility::string_to_uuid(U("12345678-abcd-efab-cdef-1234567890ab")))); + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, uuid_to_use)); query.set_filter_string(filter_string); - utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'12345678-abcd-efab-cdef-1234567890ab')")); + utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'") + converted_uuid_string + U("')")); CHECK(filter_string.compare(expected_filter_string) == 0); std::vector select_columns; @@ -3932,31 +3948,31 @@ SUITE(Table) azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::combine_filter_conditions( azure::storage::table_query::generate_filter_condition(U("PartitionKey"), azure::storage::query_comparison_operator::equal, partition_key1), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::greater_than_or_equal, U("k"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("RowKey"), azure::storage::query_comparison_operator::less_than, U("n"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("Timestamp"), azure::storage::query_comparison_operator::greater_than_or_equal, utility::datetime::from_string(U("2013-09-01T00:00:00Z"), utility::datetime::ISO_8601))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyA"), azure::storage::query_comparison_operator::not_equal, false)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyB"), azure::storage::query_comparison_operator::not_equal, 1234567890)), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, 1234567890123456789LL)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyC"), azure::storage::query_comparison_operator::not_equal, (int64_t)1234567890123456789LL)), + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyD"), azure::storage::query_comparison_operator::not_equal, 9.1234567890123456789)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyE"), azure::storage::query_comparison_operator::not_equal, U("ABCDE12345"))), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyF"), azure::storage::query_comparison_operator::not_equal, datetime_value)), - azure::storage::query_logical_operator::and, + azure::storage::query_logical_operator::op_and, azure::storage::table_query::generate_filter_condition(U("PropertyG"), azure::storage::query_comparison_operator::not_equal, std::vector(10, 'X'))), - azure::storage::query_logical_operator::and, - azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, utility::string_to_uuid(U("12345678-abcd-efab-cdef-1234567890ab")))); + azure::storage::query_logical_operator::op_and, + azure::storage::table_query::generate_filter_condition(U("PropertyH"), azure::storage::query_comparison_operator::not_equal, uuid_to_use)); query.set_filter_string(filter_string); - utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'12345678-abcd-efab-cdef-1234567890ab')")); + utility::string_t expected_filter_string = utility::string_t(U("(((((((((((PartitionKey eq '")) + partition_key1 + utility::string_t(U("') and (RowKey ge 'k')) and (RowKey lt 'n')) and (Timestamp ge datetime'2013-09-01T00:00:00Z')) and (PropertyA ne false)) and (PropertyB ne 1234567890)) and (PropertyC ne 1234567890123456789L)) and (PropertyD ne 9.1234567890123461)) and (PropertyE ne 'ABCDE12345')) and (PropertyF ne datetime'2013-01-02T03:04:05.1234567Z')) and (PropertyG ne X'58585858585858585858')) and (PropertyH ne guid'") + converted_uuid_string + U("')")); CHECK(filter_string.compare(expected_filter_string) == 0); std::vector select_columns; @@ -3981,7 +3997,6 @@ SUITE(Table) query_segment = table.execute_query_segmented(query, token, options, context); std::vector results = query_segment.results(); - CHECK(results.size() >= 0); CHECK((int)results.size() <= take_count); for (std::vector::const_iterator entity_iterator = results.cbegin(); entity_iterator != results.cend(); ++entity_iterator) diff --git a/Microsoft.WindowsAzure.Storage/tests/main.cpp b/Microsoft.WindowsAzure.Storage/tests/main.cpp index 262bbe87..a5b3cbe8 100644 --- a/Microsoft.WindowsAzure.Storage/tests/main.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/main.cpp @@ -19,6 +19,17 @@ #include "was/blob.h" +#ifndef WIN32 + +#include +#include +#include +#include +#include + +#endif + + int run_tests(const char* suite_name, const char* test_name) { UnitTest::TestReporterStdout reporter; @@ -33,6 +44,20 @@ int main(int argc, const char* argv[]) { azure::storage::operation_context::set_default_log_level(azure::storage::client_log_level::log_level_verbose); +#ifndef WIN32 + boost::log::add_common_attributes(); + boost::log::add_file_log + ( + boost::log::keywords::file_name = "test_log.log", + boost::log::keywords::format = + ( + boost::log::expressions::stream << " " << boost::log::expressions::smessage + ) + ); + +#endif + int failure_count; if (argc == 1) { diff --git a/Microsoft.WindowsAzure.Storage/tests/packages.config b/Microsoft.WindowsAzure.Storage/tests/packages.config index a7574f84..9e4930c4 100644 --- a/Microsoft.WindowsAzure.Storage/tests/packages.config +++ b/Microsoft.WindowsAzure.Storage/tests/packages.config @@ -1,4 +1,8 @@  - + + + + + \ No newline at end of file diff --git a/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp b/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp index 8634ff9e..95465c9d 100644 --- a/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/read_from_secondary_test.cpp @@ -68,7 +68,7 @@ class multi_location_test_helper multi_location_test_helper(const azure::storage::storage_uri& uri, azure::storage::storage_location initial_location, azure::storage::operation_context context, const std::vector& expected_retry_context_list, const std::vector& retry_info_list) : m_uri(uri), m_initial_location(initial_location), m_retry_info_list(retry_info_list), m_policy(std::make_shared(expected_retry_context_list, retry_info_list)), - m_request_counter(0), m_error(false), m_context(context), m_context_results_offset(context.request_results().size()) + m_request_counter(0), m_error(false), m_context(context), m_context_results_offset((int)context.request_results().size()) { m_context.set_sending_request([this] (web::http::http_request& request, azure::storage::operation_context) { diff --git a/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp b/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp index 927740c3..6ddfd594 100644 --- a/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/retry_policy_test.cpp @@ -110,6 +110,34 @@ static azure::storage::retry_info create_fake_retry_info(azure::storage::storage SUITE(Core) { + TEST(retry_info) + { + { + azure::storage::retry_info info; + + 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()); + } + + { + int current_retry_count = 2; + azure::storage::request_result last_request_result; + azure::storage::storage_location next_location = azure::storage::storage_location::secondary; + azure::storage::location_mode current_location_mode = azure::storage::location_mode::secondary_only; + + azure::storage::retry_context context(current_retry_count, last_request_result, next_location, current_location_mode); + + azure::storage::retry_info info(context); + + CHECK(info.should_retry()); + CHECK(info.target_location() == next_location); + CHECK(info.updated_location_mode() == current_location_mode); + CHECK(info.retry_interval() > std::chrono::milliseconds()); + } + } + TEST(no_retry_results) { auto allowed_delta = [] (int retry_count) -> std::chrono::milliseconds diff --git a/Microsoft.WindowsAzure.Storage/tests/service_properties_test.cpp b/Microsoft.WindowsAzure.Storage/tests/service_properties_test.cpp index 3d8dadfe..41eb5931 100644 --- a/Microsoft.WindowsAzure.Storage/tests/service_properties_test.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/service_properties_test.cpp @@ -42,6 +42,23 @@ void add_metrics_2(azure::storage::service_properties::metrics_properties& metri metrics.set_retention_policy_enabled(false); } +void add_metrics_3(azure::storage::service_properties::metrics_properties& metrics) +{ + metrics = azure::storage::service_properties::metrics_properties(); + metrics.set_version(U("1.0")); + metrics.set_enabled(false); + metrics.set_include_apis(true); + metrics.set_retention_policy_enabled(false); +} + +void add_metrics_4(azure::storage::service_properties::metrics_properties& metrics) +{ + metrics = azure::storage::service_properties::metrics_properties(); + metrics.set_version(U("1.0")); + metrics.set_enabled(false); + metrics.set_retention_policy_enabled(false); +} + void add_logging_1(azure::storage::service_properties::logging_properties& logging) { logging = azure::storage::service_properties::logging_properties(); @@ -97,13 +114,19 @@ void check_service_properties(const azure::storage::service_properties& a, const CHECK_UTF8_EQUAL(a.hour_metrics().version(), b.hour_metrics().version()); CHECK_EQUAL(a.hour_metrics().enabled(), b.hour_metrics().enabled()); - CHECK_EQUAL(a.hour_metrics().include_apis(), b.hour_metrics().include_apis()); + if (a.hour_metrics().enabled()) + { + CHECK_EQUAL(a.hour_metrics().include_apis(), b.hour_metrics().include_apis()); + } CHECK_EQUAL(a.hour_metrics().retention_policy_enabled(), b.hour_metrics().retention_policy_enabled()); CHECK_EQUAL(a.hour_metrics().retention_days(), b.hour_metrics().retention_days()); CHECK_UTF8_EQUAL(a.minute_metrics().version(), b.minute_metrics().version()); CHECK_EQUAL(a.minute_metrics().enabled(), b.minute_metrics().enabled()); - CHECK_EQUAL(a.minute_metrics().include_apis(), b.minute_metrics().include_apis()); + if (a.minute_metrics().enabled()) + { + CHECK_EQUAL(a.minute_metrics().include_apis(), b.minute_metrics().include_apis()); + } CHECK_EQUAL(a.minute_metrics().retention_policy_enabled(), b.minute_metrics().retention_policy_enabled()); CHECK_EQUAL(a.minute_metrics().retention_days(), b.minute_metrics().retention_days()); @@ -192,6 +215,20 @@ void test_service_properties(const Client& client, const Options& options, azure check_service_properties(props, client.download_service_properties(options, context)); } + { + azure::storage::service_properties_includes includes; + includes.set_hour_metrics(true); + includes.set_minute_metrics(true); + includes.set_cors(true); + add_metrics_3(temp_props.hour_metrics()); + add_metrics_4(temp_props.minute_metrics()); + client.upload_service_properties(temp_props, includes, options, context); + add_metrics_3(props.hour_metrics()); + add_metrics_4(props.minute_metrics()); + props.cors().clear(); + check_service_properties(props, client.download_service_properties(options, context)); + } + props.set_default_service_version(U("2013-08-15")); if (default_version_supported) { diff --git a/Microsoft.WindowsAzure.Storage/tests/targetver.h b/Microsoft.WindowsAzure.Storage/tests/targetver.h index 9a67c656..0f73f169 100644 --- a/Microsoft.WindowsAzure.Storage/tests/targetver.h +++ b/Microsoft.WindowsAzure.Storage/tests/targetver.h @@ -22,4 +22,6 @@ // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. +#ifdef WIN32 #include +#endif diff --git a/Microsoft.WindowsAzure.Storage/tests/test_base.cpp b/Microsoft.WindowsAzure.Storage/tests/test_base.cpp index 3215b012..19e52f67 100644 --- a/Microsoft.WindowsAzure.Storage/tests/test_base.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/test_base.cpp @@ -31,7 +31,7 @@ test_config::test_config() auto target_name = config[U("target")].as_string(); web::json::value& tenants = config[U("tenants")]; - for (web::json::array::const_iterator it = tenants.as_array().cbegin(); it != tenants.as_array().cend(); ++it) + for (web::json::array::const_iterator it = tenants.as_array().cbegin(); it != tenants.as_array().cend(); ++it) { const web::json::value& name_obj = it->at(U("name")); if (name_obj.as_string() == target_name) diff --git a/Microsoft.WindowsAzure.Storage/tests/test_helper.cpp b/Microsoft.WindowsAzure.Storage/tests/test_helper.cpp index 147bbc40..7e945d3d 100644 --- a/Microsoft.WindowsAzure.Storage/tests/test_helper.cpp +++ b/Microsoft.WindowsAzure.Storage/tests/test_helper.cpp @@ -81,7 +81,7 @@ utility::string_t get_random_string() result.reserve(SIZE); for (int i = 0; i < SIZE; ++i) { - result.push_back(U('0') + rand() % 10); + result.push_back((utility::char_t) (U('0') + rand() % 10)); } return result; } @@ -100,7 +100,7 @@ std::vector get_random_binary_data() result.reserve(SIZE); for (int i = 0; i < SIZE; ++i) { - result.push_back(rand() % 256); + result.push_back((unsigned char)(rand() % 256)); } return result; } diff --git a/Microsoft.WindowsAzure.Storage/version.rc b/Microsoft.WindowsAzure.Storage/version.rc index 0802cd3947e46f5f5f14f0522af63a4bda1008fa..7124050961b076e2c03f3817ecbc3681d02fba6b 100644 GIT binary patch delta 48 zcmX@2d_;Le9|xn!&AH_#AK?{Re1w+;0A#=o AnE(I) delta 48 zcmX@2d_;Le9|xoH&AH_#AK?{Re1w+;0AxB1 AlmGw# diff --git a/README.md b/README.md index 25e88259..39d22133 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ For general suggestions about Azure please use our [UserVoice forum](http://www. To get the source code of the SDK via git just type: ```bash -git clone git://github.com/WindowsAzure/azure-storage-cpp.git +git clone https://github.com/Azure/azure-storage-cpp.git cd azure-storage-cpp ``` @@ -58,6 +58,12 @@ Download the [NuGet Package](http://www.nuget.org/packages/wastorage). `Install-Package wastorage -Pre` +## Dependencies + +### C++ REST SDK + +This library depends on the C++ REST SDK (codename "Casablanca") 2.3.0. It can be installed through [NuGet](http://www.nuget.org/packages/cpprestsdk/2.3.0) or downloaded directly from [CodePlex](http://casablanca.codeplex.com/releases/view/129408). + ## Code Samples How-Tos focused around accomplishing specific tasks are available in the [samples folder](Microsoft.WindowsAzure.Storage/samples/). diff --git a/build.root b/build.root new file mode 100644 index 00000000..d423a1a7 --- /dev/null +++ b/build.root @@ -0,0 +1 @@ +Marker file indicating root of build system.