This commit is contained in:
Jinming Hu 2020-04-03 10:53:43 +08:00 коммит произвёл Vincent Jiang (LEI)
Родитель efbf424cfa
Коммит 34ec9f82f8
10 изменённых файлов: 254 добавлений и 9 удалений

Просмотреть файл

@ -280,6 +280,11 @@ namespace azure { namespace storage {
/// </summary>
copy = 1 << 3,
/// <summary>
/// Include saved versions of blobs.
/// <summary>
versions = 1 << 4,
/// <summary>
/// List all available committed blobs, uncommitted blobs, and snapshots, and return all metadata and copy status for those blobs.
/// </summary>
@ -1072,6 +1077,7 @@ namespace azure { namespace storage {
m_archive_status = std::move(other.m_archive_status);
m_access_tier_inferred = std::move(other.m_access_tier_inferred);
m_access_tier_change_time = std::move(other.m_access_tier_change_time);
m_version_id = std::move(other.m_version_id);
}
return *this;
}
@ -1338,6 +1344,15 @@ namespace azure { namespace storage {
return m_access_tier_change_time;
}
/// <summary>
/// Gets the version id of the blob.
/// </summary>
/// <returns>The version id the blob refers to.</returns>
const utility::string_t& version_id() const
{
return m_version_id;
}
private:
/// <summary>
@ -1366,6 +1381,7 @@ namespace azure { namespace storage {
utility::string_t m_encryption_key_sha256;
utility::datetime m_last_modified;
utility::datetime m_access_tier_change_time;
utility::string_t m_version_id;
blob_type m_type;
azure::storage::lease_status m_lease_status;
azure::storage::lease_state m_lease_state;
@ -4417,6 +4433,7 @@ namespace azure { namespace storage {
m_copy_state = std::move(other.m_copy_state);
m_name = std::move(other.m_name);
m_snapshot_time = std::move(other.m_snapshot_time);
m_version_id = std::move(other.m_version_id);
m_container = std::move(other.m_container);
m_uri = std::move(other.m_uri);
}
@ -6045,6 +6062,51 @@ namespace azure { namespace storage {
return !m_snapshot_time.empty();
}
/// <summary>
/// Sets the version id of this blob.
/// </summary>
/// <param name="version_id">The blob's version id.</param>
void set_version_id(utility::string_t version_id)
{
m_version_id = std::move(version_id);
web::uri primary_uri = m_uri.primary_uri();
web::uri secondary_uri = m_uri.secondary_uri();
for (auto uri : std::vector<std::reference_wrapper<web::uri>>{ primary_uri, secondary_uri })
{
auto query = web::http::uri::split_query(uri.get().query());
if (m_version_id.empty())
{
query.erase(protocol::uri_query_version_id);
}
else
{
query[protocol::uri_query_version_id] = m_version_id;
}
web::uri_builder builder(uri);
builder.set_query(utility::string_t());
for (const auto& q : query)
{
builder.append_query(q.first, q.second);
}
uri.get() = builder.to_uri();
}
m_uri = storage_uri(primary_uri, secondary_uri);
}
/// <summary>
/// Gets the version id of the blob, if this blob refers to a version.
/// </summary>
/// <returns>The blob's version id, if the blob refers to a version; otherwise returns an empty string.</returns>
const utility::string_t& version_id() const
{
return m_version_id;
}
/// <summary>
/// Gets the state of the most recent or pending copy operation.
/// </summary>
@ -6153,6 +6215,7 @@ namespace azure { namespace storage {
utility::string_t m_name;
utility::string_t m_snapshot_time;
utility::string_t m_version_id;
cloud_blob_container m_container;
storage_uri m_uri;
@ -9110,13 +9173,15 @@ namespace azure { namespace storage {
/// </summary>
/// <param name="blob_name">The name of the blob.</param>
/// <param name="snapshot_time">The snapshot timestamp, if the blob is a snapshot.</param>
/// <param name="version_id">The version id of the blob.</param>
/// <param name="is_current_version">If this blob version is current active version.</param>
/// <param name="container">A reference to the parent container.</param>
/// <param name="properties">A set of properties for the blob.</param>
/// <param name="metadata">User-defined metadata for the blob.</param>
/// <param name="copy_state">the state of the most recent or pending copy operation.</param>
explicit list_blob_item(utility::string_t blob_name, utility::string_t snapshot_time, cloud_blob_container container, cloud_blob_properties properties, cloud_metadata metadata, copy_state copy_state)
explicit list_blob_item(utility::string_t blob_name, utility::string_t snapshot_time, utility::string_t version_id, bool is_current_version, cloud_blob_container container, cloud_blob_properties properties, cloud_metadata metadata, copy_state copy_state)
: m_is_blob(true), m_name(std::move(blob_name)), m_container(std::move(container)),
m_snapshot_time(std::move(snapshot_time)), m_properties(std::move(properties)),
m_snapshot_time(std::move(snapshot_time)), m_version_id(std::move(version_id)), m_is_current_version(is_current_version), m_properties(std::move(properties)),
m_metadata(std::move(metadata)), m_copy_state(std::move(copy_state))
{
}
@ -9157,6 +9222,8 @@ namespace azure { namespace storage {
m_name = std::move(other.m_name);
m_container = std::move(other.m_container);
m_snapshot_time = std::move(other.m_snapshot_time);
m_version_id = std::move(other.m_version_id);
m_is_current_version = other.m_is_current_version;
m_properties = std::move(other.m_properties);
m_metadata = std::move(other.m_metadata);
m_copy_state = std::move(other.m_copy_state);
@ -9175,6 +9242,15 @@ namespace azure { namespace storage {
return m_is_blob;
}
/// <summary>
/// Gets a value indicating whether this <see cref="azure::storage::list_blob_item" /> represents current active version of a blob.
/// </summary>
/// <returns><c>true</c> if this <see cref="azure::storage::list_blob_item" /> represents current active version of a blob; otherwise, <c>false</c>.</returns>
bool is_current_version() const
{
return m_is_current_version;
}
/// <summary>
/// Returns the item as an <see cref="azure::storage::cloud_blob" /> object, if and only if it represents a cloud blob.
/// </summary>
@ -9186,7 +9262,12 @@ namespace azure { namespace storage {
throw std::runtime_error("Cannot access a cloud blob directory as cloud blob ");
}
return cloud_blob(m_name, m_snapshot_time, m_container, m_properties, m_metadata, m_copy_state);
auto blob = cloud_blob(m_name, m_snapshot_time, m_container, m_properties, m_metadata, m_copy_state);
if (!m_version_id.empty())
{
blob.set_version_id(m_version_id);
}
return blob;
}
/// <summary>
@ -9209,6 +9290,8 @@ namespace azure { namespace storage {
utility::string_t m_name;
cloud_blob_container m_container;
utility::string_t m_snapshot_time;
utility::string_t m_version_id;
bool m_is_current_version = false;
cloud_blob_properties m_properties;
cloud_metadata m_metadata;
copy_state m_copy_state;

Просмотреть файл

@ -31,6 +31,7 @@ DAT(service_file, _XPLATSTR("file"))
DAT(uri_query_timeout, _XPLATSTR("timeout"))
DAT(uri_query_resource_type, _XPLATSTR("restype"))
DAT(uri_query_snapshot, _XPLATSTR("snapshot"))
DAT(uri_query_version_id, _XPLATSTR("versionid"))
DAT(uri_query_prevsnapshot, _XPLATSTR("prevsnapshot"))
DAT(uri_query_component, _XPLATSTR("comp"))
DAT(uri_query_block_id, _XPLATSTR("blockid"))
@ -98,6 +99,7 @@ DAT(component_properties, _XPLATSTR("properties"))
DAT(component_metadata, _XPLATSTR("metadata"))
DAT(component_snapshot, _XPLATSTR("snapshot"))
DAT(component_snapshots, _XPLATSTR("snapshots"))
DAT(component_versions, _XPLATSTR("versions"))
DAT(component_uncommitted_blobs, _XPLATSTR("uncommittedblobs"))
DAT(component_lease, _XPLATSTR("lease"))
DAT(component_block, _XPLATSTR("block"))
@ -217,9 +219,10 @@ DAT(ms_header_share_next_allowed_quota_downgrade_time, _XPLATSTR("x-ms-share-nex
DAT(ms_header_share_provisioned_egress_mbps, _XPLATSTR("x-ms-share-provisioned-egress-mbps"))
DAT(ms_header_share_provisioned_ingress_mbps, _XPLATSTR("x-ms-share-provisioned-ingress-mbps"))
DAT(ms_header_share_provisioned_iops, _XPLATSTR("x-ms-share-provisioned-iops"))
DAT(ms_header_version_id, _XPLATSTR("x-ms-version-id"))
// header values
DAT(header_value_storage_version, _XPLATSTR("2019-07-07"))
DAT(header_value_storage_version, _XPLATSTR("2019-10-10"))
DAT(header_value_true, _XPLATSTR("true"))
DAT(header_value_false, _XPLATSTR("false"))
DAT(header_value_locked, _XPLATSTR("locked"))
@ -327,6 +330,8 @@ DAT(xml_blob_prefix, _XPLATSTR("BlobPrefix"))
DAT(xml_properties, _XPLATSTR("Properties"))
DAT(xml_metadata, _XPLATSTR("Metadata"))
DAT(xml_snapshot, _XPLATSTR("Snapshot"))
DAT(xml_version_id, _XPLATSTR("VersionId"))
DAT(xml_is_current_version, _XPLATSTR("IsCurrentVersion"))
DAT(xml_enumeration_results, _XPLATSTR("EnumerationResults"))
DAT(xml_service_endpoint, _XPLATSTR("ServiceEndpoint"))
DAT(xml_container_name, _XPLATSTR("ContainerName"))

Просмотреть файл

@ -151,8 +151,8 @@ namespace azure { namespace storage { namespace protocol {
{
public:
cloud_blob_list_item(web::http::uri uri, utility::string_t name, utility::string_t snapshot_time, cloud_metadata metadata, cloud_blob_properties properties, copy_state copy_state)
: m_uri(std::move(uri)), m_name(std::move(name)), m_snapshot_time(std::move(snapshot_time)), m_metadata(std::move(metadata)), m_properties(std::move(properties)), m_copy_state(std::move(copy_state))
cloud_blob_list_item(web::http::uri uri, utility::string_t name, utility::string_t snapshot_time, bool is_current_version, cloud_metadata metadata, cloud_blob_properties properties, copy_state copy_state)
: m_uri(std::move(uri)), m_name(std::move(name)), m_snapshot_time(std::move(snapshot_time)), m_is_current_version(is_current_version), m_metadata(std::move(metadata)), m_properties(std::move(properties)), m_copy_state(std::move(copy_state))
{
}
@ -171,6 +171,11 @@ namespace azure { namespace storage { namespace protocol {
return std::move(m_snapshot_time);
}
bool is_current_version() const
{
return m_is_current_version;
}
cloud_metadata move_metadata()
{
return std::move(m_metadata);
@ -191,6 +196,7 @@ namespace azure { namespace storage { namespace protocol {
web::http::uri m_uri;
utility::string_t m_name;
utility::string_t m_snapshot_time;
bool m_is_current_version;
cloud_metadata m_metadata;
cloud_blob_properties m_properties;
azure::storage::copy_state m_copy_state;
@ -274,6 +280,7 @@ namespace azure { namespace storage { namespace protocol {
utility::string_t m_name;
web::http::uri m_uri;
utility::string_t m_snapshot_time;
bool m_is_current_version = false;
cloud_metadata m_metadata;
cloud_blob_properties m_properties;
copy_state m_copy_state;

Просмотреть файл

@ -180,6 +180,12 @@ namespace azure { namespace storage { namespace protocol {
include.append(_XPLATSTR(","));
}
if ((includes & blob_listing_details::versions) != 0)
{
include.append(component_versions);
include.append(_XPLATSTR(","));
}
if (!include.empty())
{
include.pop_back();

Просмотреть файл

@ -192,6 +192,8 @@ namespace azure { namespace storage { namespace protocol {
properties.m_is_incremental_copy = response_parsers::parse_boolean(get_header_value(headers, ms_header_incremental_copy));
properties.m_access_tier_inferred = response_parsers::parse_boolean(get_header_value(headers, ms_header_access_tier_inferred));
properties.m_encryption_key_sha256 = get_header_value(headers, ms_header_encryption_key_sha256);
properties.m_version_id = get_header_value(headers, ms_header_version_id);
return properties;
}

Просмотреть файл

@ -1021,6 +1021,7 @@ namespace azure { namespace storage {
*snapshot.m_metadata = *resulting_metadata;
snapshot.m_properties->copy_from_root(*properties);
snapshot.m_properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response));
properties->update_etag_and_last_modified(protocol::blob_response_parsers::parse_blob_properties(response));
return snapshot;
});
return core::executor<cloud_blob>::execute_async(command, modified_options, context);

Просмотреть файл

@ -474,7 +474,7 @@ namespace azure { namespace storage {
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<list_blob_item_segment>, list_blob_item_segment(), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
command->set_postprocess_response([container, delimiter] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task<list_blob_item_segment>
command->set_postprocess_response([container, delimiter, includes] (const web::http::http_response& response, const request_result& result, const core::ostream_descriptor&, operation_context context) -> pplx::task<list_blob_item_segment>
{
protocol::list_blobs_reader reader(response.body());
@ -486,7 +486,9 @@ namespace azure { namespace storage {
for (auto iter = blob_items.begin(); iter != blob_items.end(); ++iter)
{
list_blob_items.push_back(list_blob_item(iter->move_name(), iter->move_snapshot_time(), container, iter->move_properties(), iter->move_metadata(), iter->move_copy_state()));
auto properties = iter->move_properties();
utility::string_t version_id = (includes & blob_listing_details::values::versions) ? properties.version_id() : utility::string_t();
list_blob_items.push_back(list_blob_item(iter->move_name(), iter->move_snapshot_time(), std::move(version_id), iter->is_current_version(), container, std::move(properties), iter->move_metadata(), iter->move_copy_state()));
}
for (auto iter = blob_prefix_items.begin(); iter != blob_prefix_items.end(); ++iter)

Просмотреть файл

@ -32,6 +32,7 @@ namespace azure { namespace storage {
{
m_etag = parsed_properties.etag();
m_last_modified = parsed_properties.last_modified();
m_version_id = parsed_properties.version_id();
}
void cloud_blob_properties::copy_from_root(const cloud_blob_properties& root_blob_properties)

Просмотреть файл

@ -330,6 +330,18 @@ namespace azure { namespace storage { namespace protocol {
return;
}
if (element_name == xml_version_id)
{
m_properties.m_version_id = get_current_element_text();
return;
}
if (element_name == xml_is_current_version)
{
m_is_current_version = response_parsers::parse_boolean(get_current_element_text());
return;
}
if (element_name == xml_name)
{
m_name = get_current_element_text();
@ -350,10 +362,11 @@ namespace azure { namespace storage { namespace protocol {
{
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(m_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), m_is_current_version, 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_is_current_version = false;
m_metadata = azure::storage::cloud_metadata();
m_properties = azure::storage::cloud_blob_properties();
m_copy_state = azure::storage::copy_state();

Просмотреть файл

@ -0,0 +1,125 @@
// -----------------------------------------------------------------------------------------
// <copyright file="blob_lease_test.cpp" company="Microsoft">
// Copyright 2020 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.
// </copyright>
// -----------------------------------------------------------------------------------------
#include "stdafx.h"
#include "blob_test_base.h"
#include "check_macros.h"
#include <set>
SUITE(Blob)
{
TEST_FIXTURE(block_blob_test_base, blob_versioning_properties)
{
utility::string_t blob_content = _XPLATSTR("test");
m_blob.upload_text(blob_content, azure::storage::access_condition(), azure::storage::blob_request_options(), m_context);
auto version_id0 = m_blob.properties().version_id();
CHECK(!version_id0.empty());
m_blob.download_attributes();
CHECK(version_id0 == m_blob.properties().version_id());
m_blob.upload_text(blob_content, azure::storage::access_condition(), azure::storage::blob_request_options(), m_context);
auto version_id1 = m_blob.properties().version_id();
CHECK(version_id1 != version_id0);
m_blob.metadata()[_XPLATSTR("k1")] = _XPLATSTR("value1");
m_blob.upload_metadata();
auto version_id2 = m_blob.properties().version_id();
CHECK(version_id2 != version_id1);
m_blob.create_snapshot();
auto version_id3 = m_blob.properties().version_id();
CHECK(version_id3 != version_id2);
m_blob.properties().set_content_md5(utility::string_t());
m_blob.upload_block_list(std::vector<azure::storage::block_list_item>());
auto version_id4 = m_blob.properties().version_id();
CHECK(version_id4 != version_id3);
CHECK(utility::string_t() == m_blob.download_text());
CHECK(version_id4 == m_blob.properties().version_id());
m_blob.start_copy(m_blob.uri());
auto version_id5 = m_blob.properties().version_id();
CHECK(version_id5 != version_id4);
auto blobs = m_container.list_blobs_segmented(utility::string_t(), true, azure::storage::blob_listing_details::none, 0, azure::storage::continuation_token(), azure::storage::blob_request_options(), azure::storage::operation_context());
CHECK_EQUAL(1, blobs.results().size());
CHECK(blobs.results()[0].is_blob());
CHECK(blobs.results()[0].is_current_version());
auto blob = blobs.results()[0].as_blob();
CHECK(blob.version_id().empty());
CHECK(!blob.properties().version_id().empty());
blobs = m_container.list_blobs_segmented(utility::string_t(), true, azure::storage::blob_listing_details::versions, 0, azure::storage::continuation_token(), azure::storage::blob_request_options(), azure::storage::operation_context());
std::set<utility::string_t> versions;
for (const auto& t : blobs.results())
{
if (t.is_blob())
{
versions.emplace(t.as_blob().version_id());
}
}
CHECK(versions.find(version_id0) != versions.end());
CHECK(versions.find(version_id1) != versions.end());
CHECK(versions.find(version_id2) != versions.end());
CHECK(versions.find(version_id3) != versions.end());
CHECK(versions.find(version_id4) != versions.end());
CHECK(versions.find(version_id5) != versions.end());
for (const auto& t : blobs.results())
{
if (t.is_blob())
{
blob = t.as_blob();
CHECK(!blob.version_id().empty());
if (t.is_current_version())
{
CHECK(blob.version_id() == version_id5);
CHECK(blob.properties().version_id() == version_id5);
}
if (blob.version_id() == version_id0)
{
azure::storage::cloud_block_blob block_blob(blob);
CHECK(blob_content == block_blob.download_text());
blob.download_attributes();
CHECK(blob.metadata() == azure::storage::cloud_metadata());
}
}
}
m_blob.delete_blob(azure::storage::delete_snapshots_option::include_snapshots, azure::storage::access_condition(), azure::storage::blob_request_options(), azure::storage::operation_context());
blobs = m_container.list_blobs_segmented(utility::string_t(), true, azure::storage::blob_listing_details::versions, 0, azure::storage::continuation_token(), azure::storage::blob_request_options(), azure::storage::operation_context());
CHECK(!blobs.results().empty());
for (const auto&t : blobs.results())
{
if (t.is_blob())
{
CHECK(!t.is_current_version());
blob = t.as_blob();
blob.delete_blob();
}
}
blobs = m_container.list_blobs_segmented(utility::string_t(), true, azure::storage::blob_listing_details::versions, 0, azure::storage::continuation_token(), azure::storage::blob_request_options(), azure::storage::operation_context());
CHECK(blobs.results().empty());
}
}