Add more APIs in storage sdk (#169)

* Add xml serializer/deserializer

* Add blob service client, add undelete, set access tier, start copy, abort copy, create snapshot, stage block from uri

* add support for conditional headers

* support range download

* Change the helper functions order to alphabetical

so that we always get the same result in different environemnts.

* use c++ casting

* Add support for append blob and page blob

* remove redundant ; added by auto-generator

* Remove BlobType in BlockBlob::Upload

* Rename blob_client_options.hpp->blob_options.hpp

* Remove API version in request options
This commit is contained in:
JinmingHu 2020-06-15 02:31:36 -07:00 committed by GitHub
parent f604a1dd00
commit 4366159c50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 4803 additions and 729 deletions

View File

@ -16,12 +16,15 @@ set (AZURE_STORAGE_BLOB_HEADER
inc/common/common_headers_request_policy.hpp
inc/common/shared_key_policy.hpp
inc/common/crypt.hpp
inc/common/xml_wrapper.hpp
inc/blobs/blob.hpp
inc/blobs/blob_service_client.hpp
inc/blobs/blob_container_client.hpp
inc/blobs/blob_client.hpp
inc/blobs/block_blob_client.hpp
inc/blobs/blob_container_client.hpp
inc/blobs/blob_client_options.hpp
inc/blobs/blob_container_client_options.hpp
inc/blobs/page_blob_client.hpp
inc/blobs/append_blob_client.hpp
inc/blobs/blob_options.hpp
inc/blobs/internal/protocol/blob_rest_client.hpp
)
@ -31,14 +34,18 @@ set (AZURE_STORAGE_DATALAKE_HEADER
)
set (AZURE_STORAGE_BLOB_SOURCE
src/blobs/blob_client.cpp
src/blobs/block_blob_client.cpp
src/blobs/blob_container_client.cpp
src/common/storage_credential.cpp
src/common/storage_url_builder.cpp
src/common/common_headers_request_policy.cpp
src/common/shared_key_policy.cpp
src/common/crypt.cpp
src/common/xml_wrapper.cpp
src/blobs/blob_service_client.cpp
src/blobs/blob_container_client.cpp
src/blobs/blob_client.cpp
src/blobs/block_blob_client.cpp
src/blobs/page_blob_client.cpp
src/blobs/append_blob_client.cpp
)
set (AZURE_STORAGE_DATALAKE_SOURCE

View File

@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include "blob_options.hpp"
#include "blobs/blob_client.hpp"
#include "common/storage_credential.hpp"
#include "internal/protocol/blob_rest_client.hpp"
#include <string>
namespace Azure { namespace Storage { namespace Blobs {
class AppendBlobClient : public BlobClient {
public:
// connection string
static AppendBlobClient CreateFromConnectionString(
const std::string& connectionString,
const std::string& containerName,
const std::string& blobName,
const AppendBlobClientOptions& options = AppendBlobClientOptions());
// shared key auth
explicit AppendBlobClient(
const std::string& blobUri,
std::shared_ptr<SharedKeyCredential> credential,
const AppendBlobClientOptions& options = AppendBlobClientOptions());
// token auth
explicit AppendBlobClient(
const std::string& blobUri,
std::shared_ptr<TokenCredential> credential,
const AppendBlobClientOptions& options = AppendBlobClientOptions());
// anonymous/SAS/customized pipeline auth
explicit AppendBlobClient(
const std::string& blobUri,
const AppendBlobClientOptions& options = AppendBlobClientOptions());
AppendBlobClient WithSnapshot(const std::string& snapshot) const;
BlobContentInfo Create(const CreateAppendBlobOptions& options = CreateAppendBlobOptions());
BlobAppendInfo AppendBlock(
// TODO: We don't have BodyStream for now.
std::vector<uint8_t> content,
const AppendBlockOptions& options = AppendBlockOptions());
private:
explicit AppendBlobClient(BlobClient blobClient);
};
}}} // namespace Azure::Storage::Blobs

View File

@ -3,6 +3,9 @@
#pragma once
#include "blobs/append_blob_client.hpp"
#include "blobs/blob_client.hpp"
#include "blobs/blob_container_client.hpp"
#include "blobs/blob_service_client.hpp"
#include "blobs/block_blob_client.hpp"
#include "blobs/page_blob_client.hpp"

View File

@ -3,7 +3,7 @@
#pragma once
#include "blob_client_options.hpp"
#include "blob_options.hpp"
#include "common/storage_credential.hpp"
#include "common/storage_url_builder.hpp"
#include "internal/protocol/blob_rest_client.hpp"
@ -40,21 +40,39 @@ namespace Azure { namespace Storage { namespace Blobs {
const std::string& blobUri,
const BlobClientOptions& options = BlobClientOptions());
BlobClient WithSnapshot(const std::string& snapshot);
BlobClient WithSnapshot(const std::string& snapshot) const;
BlobProperties GetProperties(
const GetBlobPropertiesOptions& options = GetBlobPropertiesOptions());
const GetBlobPropertiesOptions& options = GetBlobPropertiesOptions()) const;
BlobInfo SetHttpHeaders(const SetBlobHttpHeadersOptions& options = SetBlobHttpHeadersOptions());
BlobInfo SetHttpHeaders(
const SetBlobHttpHeadersOptions& options = SetBlobHttpHeadersOptions()) const;
BlobInfo SetMetadata(
std::map<std::string, std::string> metadata,
const SetBlobMetadataOptions& options = SetBlobMetadataOptions());
const SetBlobMetadataOptions& options = SetBlobMetadataOptions()) const;
BasicResponse SetAccessTier(
AccessTier Tier,
const SetAccessTierOptions& options = SetAccessTierOptions()) const;
BlobCopyInfo StartCopyFromUri(
const std::string& sourceUri,
const StartCopyFromUriOptions& options = StartCopyFromUriOptions()) const;
BasicResponse AbortCopyFromUri(
const std::string& copyId,
const AbortCopyFromUriOptions& options = AbortCopyFromUriOptions()) const;
FlattenedDownloadProperties Download(
const DownloadBlobOptions& options = DownloadBlobOptions());
const DownloadBlobOptions& options = DownloadBlobOptions()) const;
BasicResponse Delete(const DeleteBlobOptions& options = DeleteBlobOptions());
BlobSnapshotInfo CreateSnapshot(
const CreateSnapshotOptions& options = CreateSnapshotOptions()) const;
BasicResponse Delete(const DeleteBlobOptions& options = DeleteBlobOptions()) const;
BasicResponse Undelete(const UndeleteBlobOptions& options = UndeleteBlobOptions()) const;
protected:
UrlBuilder m_blobUrl;

View File

@ -1,88 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include "internal/protocol/blob_rest_client.hpp"
#include <limits>
#include <string>
#include <utility>
namespace Azure { namespace Storage { namespace Blobs {
struct BlobClientOptions
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
};
struct BlockBlobClientOptions : public BlobClientOptions
{
};
struct GetBlobPropertiesOptions
{
Azure::Core::Context Context;
};
struct SetBlobHttpHeadersOptions
{
Azure::Core::Context Context;
std::string ContentType;
std::string ContentEncoding;
std::string ContentLanguage;
std::string ContentMD5;
std::string CacheControl;
std::string ContentDisposition;
};
struct SetBlobMetadataOptions
{
Azure::Core::Context Context;
};
struct DownloadBlobOptions
{
Azure::Core::Context Context;
uint64_t Offset = std::numeric_limits<uint64_t>::max();
uint64_t Length = 0;
};
struct DeleteBlobOptions
{
Azure::Core::Context Context;
DeleteSnapshotsOption DeleteSnapshots = DeleteSnapshotsOption::None;
};
struct UploadBlobOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
BlobHttpHeaders Properties;
std::map<std::string, std::string> Metadata;
AccessTier Tier = AccessTier::Unknown;
};
struct StageBlockOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
};
struct CommitBlockListOptions
{
Azure::Core::Context Context;
BlobHttpHeaders Properties;
std::map<std::string, std::string> Metadata;
AccessTier Tier = AccessTier::Unknown;
};
struct GetBlockListOptions
{
Azure::Core::Context Context;
BlockListTypeOption ListType = BlockListTypeOption::All;
};
}}} // namespace Azure::Storage::Blobs

View File

@ -3,7 +3,7 @@
#pragma once
#include "blob_container_client_options.hpp"
#include "blob_options.hpp"
#include "blobs/blob_client.hpp"
#include "common/storage_credential.hpp"
#include "common/storage_url_builder.hpp"
@ -40,21 +40,23 @@ namespace Azure { namespace Storage { namespace Blobs {
const std::string& containerUri,
const BlobContainerClientOptions& options = BlobContainerClientOptions());
BlobClient GetBlobClient(const std::string& blobName);
BlobClient GetBlobClient(const std::string& blobName) const;
BlobContainerInfo Create(
const CreateBlobContainerOptions& options = CreateBlobContainerOptions());
const CreateBlobContainerOptions& options = CreateBlobContainerOptions()) const;
BasicResponse Delete(const DeleteBlobContainerOptions& options = DeleteBlobContainerOptions());
BasicResponse Delete(
const DeleteBlobContainerOptions& options = DeleteBlobContainerOptions()) const;
BlobContainerProperties GetProperties(
const GetBlobContainerPropertiesOptions& options = GetBlobContainerPropertiesOptions());
const GetBlobContainerPropertiesOptions& options
= GetBlobContainerPropertiesOptions()) const;
BlobContainerInfo SetMetadata(
std::map<std::string, std::string> metadata,
SetBlobContainerMetadataOptions options = SetBlobContainerMetadataOptions());
SetBlobContainerMetadataOptions options = SetBlobContainerMetadataOptions()) const;
BlobsFlatSegment ListBlobs(const ListBlobsOptions& options = ListBlobsOptions());
BlobsFlatSegment ListBlobs(const ListBlobsOptions& options = ListBlobsOptions()) const;
private:
UrlBuilder m_ContainerUri;

View File

@ -1,51 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include "internal/protocol/blob_rest_client.hpp"
#include <map>
#include <string>
#include <vector>
namespace Azure { namespace Storage { namespace Blobs {
struct BlobContainerClientOptions
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
};
struct CreateBlobContainerOptions
{
Azure::Core::Context Context;
PublicAccessType AccessType = PublicAccessType::Private;
std::map<std::string, std::string> Metadata;
};
struct DeleteBlobContainerOptions
{
Azure::Core::Context Context;
};
struct GetBlobContainerPropertiesOptions
{
Azure::Core::Context Context;
};
struct SetBlobContainerMetadataOptions
{
Azure::Core::Context Context;
};
struct ListBlobsOptions
{
Azure::Core::Context Context;
std::string Prefix;
std::string Delimiter;
std::string Marker;
int MaxResults = 0;
std::vector<ListBlobsIncludeItem> Include;
};
}}} // namespace Azure::Storage::Blobs

View File

@ -0,0 +1,353 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include "internal/protocol/blob_rest_client.hpp"
#include <limits>
#include <string>
#include <utility>
namespace Azure { namespace Storage { namespace Blobs {
struct BlobServiceClientOptions
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
};
struct ListBlobContainersOptions
{
Azure::Core::Context Context;
std::string Prefix;
std::string Marker;
int MaxResults = 0;
std::vector<ListBlobContainersIncludeOption> Include;
};
struct GetUserDelegationKeyOptions
{
Azure::Core::Context Context;
std::string StartsOn;
};
struct BlobContainerClientOptions
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
};
struct CreateBlobContainerOptions
{
Azure::Core::Context Context;
PublicAccessType AccessType = PublicAccessType::Private;
std::map<std::string, std::string> Metadata;
};
struct DeleteBlobContainerOptions
{
Azure::Core::Context Context;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
};
struct GetBlobContainerPropertiesOptions
{
Azure::Core::Context Context;
};
struct SetBlobContainerMetadataOptions
{
Azure::Core::Context Context;
std::string IfModifiedSince;
};
struct ListBlobsOptions
{
Azure::Core::Context Context;
std::string Prefix;
std::string Delimiter;
std::string Marker;
int MaxResults = 0;
std::vector<ListBlobsIncludeItem> Include;
};
struct BlobClientOptions
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
};
struct BlockBlobClientOptions : public BlobClientOptions
{
};
struct AppendBlobClientOptions : public BlobClientOptions
{
};
struct PageBlobClientOptions : public BlobClientOptions
{
};
struct GetBlobPropertiesOptions
{
Azure::Core::Context Context;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct SetBlobHttpHeadersOptions
{
Azure::Core::Context Context;
std::string ContentType;
std::string ContentEncoding;
std::string ContentLanguage;
std::string ContentMD5;
std::string CacheControl;
std::string ContentDisposition;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct SetBlobMetadataOptions
{
Azure::Core::Context Context;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct SetAccessTierOptions
{
Azure::Core::Context Context;
Blobs::RehydratePriority RehydratePriority = Blobs::RehydratePriority::Unknown;
};
struct StartCopyFromUriOptions
{
Azure::Core::Context Context;
std::map<std::string, std::string> Metadata;
std::string LeaseId;
std::string SourceLeaseId;
AccessTier Tier = AccessTier::Unknown;
Blobs::RehydratePriority RehydratePriority = Blobs::RehydratePriority::Unknown;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
std::string SourceIfModifiedSince;
std::string SourceIfUnmodifiedSince;
std::string SourceIfMatch;
std::string SourceIfNoneMatch;
};
struct AbortCopyFromUriOptions
{
Azure::Core::Context Context;
std::string LeaseId;
};
struct DownloadBlobOptions
{
Azure::Core::Context Context;
uint64_t Offset = std::numeric_limits<uint64_t>::max(); // max means the whole blob
uint64_t Length = 0; // 0 means till the end
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct CreateSnapshotOptions
{
Azure::Core::Context Context;
std::map<std::string, std::string> Metadata;
std::string LeaseId;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct DeleteBlobOptions
{
Azure::Core::Context Context;
DeleteSnapshotsOption DeleteSnapshots = DeleteSnapshotsOption::None;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct UndeleteBlobOptions
{
Azure::Core::Context Context;
};
struct UploadBlobOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
BlobHttpHeaders Properties;
std::map<std::string, std::string> Metadata;
AccessTier Tier = AccessTier::Unknown;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct StageBlockOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
};
struct StageBlockFromUriOptions
{
Azure::Core::Context Context;
uint64_t SourceOffset = std::numeric_limits<uint64_t>::max();
uint64_t SourceLength = 0;
std::string ContentMD5;
std::string ContentCRC64;
std::string LeaseId;
std::string SourceIfModifiedSince;
std::string SourceIfUnmodifiedSince;
std::string SourceIfMatch;
std::string SourceIfNoneMatch;
};
struct CommitBlockListOptions
{
Azure::Core::Context Context;
BlobHttpHeaders Properties;
std::map<std::string, std::string> Metadata;
AccessTier Tier = AccessTier::Unknown;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct GetBlockListOptions
{
Azure::Core::Context Context;
BlockListTypeOption ListType = BlockListTypeOption::All;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct CreateAppendBlobOptions
{
Azure::Core::Context Context;
BlobHttpHeaders Properties;
std::map<std::string, std::string> Metadata;
AccessTier Tier = AccessTier::Unknown;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct AppendBlockOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
std::string LeaseId;
uint64_t MaxSize = std::numeric_limits<uint64_t>::max();
uint64_t AppendPosition = std::numeric_limits<uint64_t>::max();
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct CreatePageBlobOptions
{
Azure::Core::Context Context;
uint64_t SequenceNumber = 0;
BlobHttpHeaders Properties;
std::map<std::string, std::string> Metadata;
AccessTier Tier = AccessTier::Unknown;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct UploadPagesOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
std::string LeaseId;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct UploadPagesFromUriOptions
{
Azure::Core::Context Context;
std::string ContentMD5;
std::string ContentCRC64;
std::string LeaseId;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct ClearPagesOptions
{
Azure::Core::Context Context;
std::string LeaseId;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct ResizePageBlobOptions
{
Azure::Core::Context Context;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct GetPageRangesOptions
{
Azure::Core::Context Context;
std::string PreviousSnapshot;
std::string PreviousSnapshotUrl;
uint64_t Offset = 0;
uint64_t Length = 0;
std::string LeaseId;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
struct IncrementalCopyPageBlobOptions
{
Azure::Core::Context Context;
std::string IfModifiedSince;
std::string IfUnmodifiedSince;
std::string IfMatch;
std::string IfNoneMatch;
};
}}} // namespace Azure::Storage::Blobs

View File

@ -0,0 +1,51 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include "blob_options.hpp"
#include "common/storage_credential.hpp"
#include "common/storage_url_builder.hpp"
#include "internal/protocol/blob_rest_client.hpp"
#include <memory>
#include <string>
namespace Azure { namespace Storage { namespace Blobs {
class BlobServiceClient {
public:
// connection string
static BlobServiceClient CreateFromConnectionString(
const std::string& connectionString,
const BlobServiceClientOptions& options = BlobServiceClientOptions());
// shared key auth
explicit BlobServiceClient(
const std::string& serviceUri,
std::shared_ptr<SharedKeyCredential> credential,
const BlobServiceClientOptions& options = BlobServiceClientOptions());
// token auth
explicit BlobServiceClient(
const std::string& serviceUri,
std::shared_ptr<TokenCredential> credential,
const BlobServiceClientOptions& options = BlobServiceClientOptions());
// anonymous/SAS/customized pipeline auth
explicit BlobServiceClient(
const std::string& serviceUri,
const BlobServiceClientOptions& options = BlobServiceClientOptions());
ListContainersSegment ListBlobContainersSegment(
const ListBlobContainersOptions& options = ListBlobContainersOptions()) const;
UserDelegationKey GetUserDelegationKey(
const std::string& expiresOn,
const GetUserDelegationKeyOptions& options = GetUserDelegationKeyOptions()) const;
protected:
UrlBuilder m_serviceUrl;
std::shared_ptr<Azure::Core::Http::HttpPipeline> m_pipeline;
};
}}} // namespace Azure::Storage::Blobs

View File

@ -3,7 +3,7 @@
#pragma once
#include "blob_client_options.hpp"
#include "blob_options.hpp"
#include "blobs/blob_client.hpp"
#include "common/storage_credential.hpp"
#include "internal/protocol/blob_rest_client.hpp"
@ -39,24 +39,30 @@ namespace Azure { namespace Storage { namespace Blobs {
const std::string& blobUri,
const BlockBlobClientOptions& options = BlockBlobClientOptions());
BlockBlobClient WithSnapshot(const std::string& snapshot);
BlockBlobClient WithSnapshot(const std::string& snapshot) const;
BlobContentInfo Upload(
// TODO: We don't have BodyStream for now.
std::vector<uint8_t> content,
const UploadBlobOptions& options = UploadBlobOptions());
const UploadBlobOptions& options = UploadBlobOptions()) const;
BlockInfo StageBlock(
const std::string& blockId,
// TODO: We don't have BodyStream for now.
std::vector<uint8_t> content,
const StageBlockOptions& options = StageBlockOptions());
const StageBlockOptions& options = StageBlockOptions()) const;
BlockInfo StageBlockFromUri(
const std::string& blockId,
const std::string& sourceUri,
const StageBlockFromUriOptions& options = StageBlockFromUriOptions()) const;
BlobContentInfo CommitBlockList(
const std::vector<std::pair<BlockType, std::string>>& blockIds,
const CommitBlockListOptions& options = CommitBlockListOptions());
const CommitBlockListOptions& options = CommitBlockListOptions()) const;
BlobBlockListInfo GetBlockList(const GetBlockListOptions& options = GetBlockListOptions());
BlobBlockListInfo GetBlockList(
const GetBlockListOptions& options = GetBlockListOptions()) const;
private:
explicit BlockBlobClient(BlobClient blobClient);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include "blob_options.hpp"
#include "blobs/blob_client.hpp"
#include "common/storage_credential.hpp"
#include "internal/protocol/blob_rest_client.hpp"
#include <string>
namespace Azure { namespace Storage { namespace Blobs {
class PageBlobClient : public BlobClient {
public:
// connection string
static PageBlobClient CreateFromConnectionString(
const std::string& connectionString,
const std::string& containerName,
const std::string& blobName,
const PageBlobClientOptions& options = PageBlobClientOptions());
// shared key auth
explicit PageBlobClient(
const std::string& blobUri,
std::shared_ptr<SharedKeyCredential> credential,
const PageBlobClientOptions& options = PageBlobClientOptions());
// token auth
explicit PageBlobClient(
const std::string& blobUri,
std::shared_ptr<TokenCredential> credential,
const PageBlobClientOptions& options = PageBlobClientOptions());
// anonymous/SAS/customized pipeline auth
explicit PageBlobClient(
const std::string& blobUri,
const PageBlobClientOptions& options = PageBlobClientOptions());
PageBlobClient WithSnapshot(const std::string& snapshot) const;
BlobContentInfo Create(
uint64_t blobContentLength,
const CreatePageBlobOptions& options = CreatePageBlobOptions());
PageInfo UploadPages(
// TODO: We don't have BodyStream for now.
std::vector<uint8_t> content,
uint64_t offset,
const UploadPagesOptions& options = UploadPagesOptions());
PageInfo UploadPagesFromUri(
std::string sourceUri,
uint64_t sourceOffset,
uint64_t sourceLength,
uint64_t destinationoffset,
const UploadPagesFromUriOptions& options = UploadPagesFromUriOptions());
PageInfo ClearPages(
uint64_t offset,
uint64_t length,
const ClearPagesOptions& options = ClearPagesOptions());
PageBlobInfo Resize(
uint64_t blobContentLength,
const ResizePageBlobOptions& options = ResizePageBlobOptions());
PageRangesInfo GetPageRanges(const GetPageRangesOptions& options = GetPageRangesOptions());
BlobCopyInfo StartCopyIncremental(
const std::string& sourceUri,
const IncrementalCopyPageBlobOptions& options = IncrementalCopyPageBlobOptions());
private:
explicit PageBlobClient(BlobClient blobClient);
};
}}} // namespace Azure::Storage::Blobs

View File

@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#pragma once
#include <functional>
#include <string>
struct _xmlTextReader;
struct _xmlTextWriter;
struct _xmlBuffer;
namespace Azure { namespace Storage {
enum class XmlNodeType
{
StartTag,
EndTag,
SelfClosingTag,
Text,
Attribute,
End,
};
struct XmlNode
{
explicit XmlNode(XmlNodeType type, const char* name = nullptr, const char* value = nullptr)
: Type(type), Name(name), Value(value)
{
}
XmlNodeType Type;
const char* Name;
const char* Value;
};
class XmlReader {
public:
explicit XmlReader(const char* data, std::size_t length);
~XmlReader();
XmlNode Read();
private:
_xmlTextReader* m_reader = nullptr;
bool m_readingAttributes = false;
};
class XmlWriter {
public:
explicit XmlWriter();
~XmlWriter();
void Write(XmlNode node);
std::string GetDocument();
private:
_xmlBuffer* m_buffer = nullptr;
_xmlTextWriter* m_writer = nullptr;
};
}} // namespace Azure::Storage

View File

@ -0,0 +1,93 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "blobs/append_blob_client.hpp"
#include "common/storage_common.hpp"
namespace Azure { namespace Storage { namespace Blobs {
AppendBlobClient AppendBlobClient::CreateFromConnectionString(
const std::string& connectionString,
const std::string& containerName,
const std::string& blobName,
const AppendBlobClientOptions& options)
{
AppendBlobClient newClient(
BlobClient::CreateFromConnectionString(connectionString, containerName, blobName, options));
return newClient;
}
AppendBlobClient::AppendBlobClient(
const std::string& blobUri,
std::shared_ptr<SharedKeyCredential> credential,
const AppendBlobClientOptions& options)
: BlobClient(blobUri, std::move(credential), options)
{
}
AppendBlobClient::AppendBlobClient(
const std::string& blobUri,
std::shared_ptr<TokenCredential> credential,
const AppendBlobClientOptions& options)
: BlobClient(blobUri, std::move(credential), options)
{
}
AppendBlobClient::AppendBlobClient(
const std::string& blobUri,
const AppendBlobClientOptions& options)
: BlobClient(blobUri, options)
{
}
AppendBlobClient::AppendBlobClient(BlobClient blobClient) : BlobClient(std::move(blobClient)) {}
AppendBlobClient AppendBlobClient::WithSnapshot(const std::string& snapshot) const
{
AppendBlobClient newClient(*this);
if (snapshot.empty())
{
newClient.m_blobUrl.RemoveQuery("snapshot");
}
else
{
newClient.m_blobUrl.AppendQuery("snapshot", snapshot);
}
return newClient;
}
BlobContentInfo AppendBlobClient::Create(const CreateAppendBlobOptions& options)
{
BlobRestClient::AppendBlob::CreateOptions protocolLayerOptions;
protocolLayerOptions.Properties = options.Properties;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.Tier = options.Tier;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::AppendBlob::Create(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobAppendInfo AppendBlobClient::AppendBlock(
std::vector<uint8_t> content,
const AppendBlockOptions& options)
{
BlobRestClient::AppendBlob::AppendBlockOptions protocolLayerOptions;
protocolLayerOptions.BodyBuffer = &content;
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.ContentCRC64 = options.ContentCRC64;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.MaxSize = options.MaxSize;
protocolLayerOptions.AppendPosition = options.AppendPosition;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::AppendBlob::AppendBlock(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
}}} // namespace Azure::Storage::Blobs

View File

@ -123,48 +123,62 @@ namespace Azure { namespace Storage { namespace Blobs {
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobClient BlobClient::WithSnapshot(const std::string& snapshot)
BlobClient BlobClient::WithSnapshot(const std::string& snapshot) const
{
BlobClient newClient(*this);
if (snapshot.empty())
{
m_blobUrl.RemoveQuery("snapshot");
newClient.m_blobUrl.RemoveQuery("snapshot");
}
else
{
m_blobUrl.AppendQuery("snapshot", snapshot);
newClient.m_blobUrl.AppendQuery("snapshot", snapshot);
}
return newClient;
}
FlattenedDownloadProperties BlobClient::Download(const DownloadBlobOptions& options)
FlattenedDownloadProperties BlobClient::Download(const DownloadBlobOptions& options) const
{
BlobRestClient::Blob::DownloadOptions protocolLayerOptions;
if (options.Offset != std::numeric_limits<decltype(options.Offset)>::max())
{
protocolLayerOptions.Range
= std::make_pair(options.Offset, options.Offset + options.Length - 1);
if (options.Length == 0)
{
protocolLayerOptions.Range
= std::make_pair(options.Offset, std::numeric_limits<decltype(options.Offset)>::max());
}
else
{
protocolLayerOptions.Range
= std::make_pair(options.Offset, options.Offset + options.Length - 1);
}
}
else
{
protocolLayerOptions.Range
= std::make_pair(std::numeric_limits<uint64_t>::max(), uint64_t(0));
}
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::Download(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobProperties BlobClient::GetProperties(const GetBlobPropertiesOptions& options)
BlobProperties BlobClient::GetProperties(const GetBlobPropertiesOptions& options) const
{
unused(options);
BlobRestClient::Blob::GetPropertiesOptions protocolLayerOptions;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::GetProperties(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobInfo BlobClient::SetHttpHeaders(const SetBlobHttpHeadersOptions& options)
BlobInfo BlobClient::SetHttpHeaders(const SetBlobHttpHeadersOptions& options) const
{
BlobRestClient::Blob::SetHttpHeadersOptions protocolLayerOptions;
protocolLayerOptions.ContentType = options.ContentType;
@ -173,27 +187,102 @@ namespace Azure { namespace Storage { namespace Blobs {
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.CacheControl = options.CacheControl;
protocolLayerOptions.ContentDisposition = options.ContentDisposition;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::SetHttpHeaders(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobInfo BlobClient::SetMetadata(
std::map<std::string, std::string> metadata,
const SetBlobMetadataOptions& options)
const SetBlobMetadataOptions& options) const
{
unused(options);
BlobRestClient::Blob::SetMetadataOptions protocolLayerOptions;
protocolLayerOptions.Metadata = std::move(metadata);
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::SetMetadata(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::Delete(const DeleteBlobOptions& options)
BasicResponse BlobClient::SetAccessTier(AccessTier Tier, const SetAccessTierOptions& options)
const
{
BlobRestClient::Blob::SetAccessTierOptions protocolLayerOptions;
protocolLayerOptions.Tier = Tier;
protocolLayerOptions.RehydratePriority = options.RehydratePriority;
return BlobRestClient::Blob::SetAccessTier(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobCopyInfo BlobClient::StartCopyFromUri(
const std::string& sourceUri,
const StartCopyFromUriOptions& options) const
{
BlobRestClient::Blob::StartCopyFromUriOptions protocolLayerOptions;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.SourceUri = sourceUri;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.SourceLeaseId = options.SourceLeaseId;
protocolLayerOptions.Tier = options.Tier;
protocolLayerOptions.RehydratePriority = options.RehydratePriority;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
protocolLayerOptions.SourceIfModifiedSince = options.SourceIfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.SourceIfMatch = options.SourceIfMatch;
protocolLayerOptions.SourceIfNoneMatch = options.SourceIfNoneMatch;
return BlobRestClient::Blob::StartCopyFromUri(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::AbortCopyFromUri(
const std::string& copyId,
const AbortCopyFromUriOptions& options) const
{
BlobRestClient::Blob::AbortCopyFromUriOptions protocolLayerOptions;
protocolLayerOptions.CopyId = copyId;
protocolLayerOptions.LeaseId = options.LeaseId;
return BlobRestClient::Blob::AbortCopyFromUri(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobSnapshotInfo BlobClient::CreateSnapshot(const CreateSnapshotOptions& options) const
{
BlobRestClient::Blob::CreateSnapshotOptions protocolLayerOptions;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::CreateSnapshot(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::Delete(const DeleteBlobOptions& options) const
{
BlobRestClient::Blob::DeleteOptions protocolLayerOptions;
protocolLayerOptions.DeleteSnapshots = options.DeleteSnapshots;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::Blob::Delete(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BasicResponse BlobClient::Undelete(const UndeleteBlobOptions& options) const
{
BlobRestClient::Blob::UndeleteOptions protocolLayerOptions;
return BlobRestClient::Blob::Undelete(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
}}} // namespace Azure::Storage::Blobs

View File

@ -123,7 +123,7 @@ namespace Azure { namespace Storage { namespace Blobs {
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobContainerInfo BlobContainerClient::Create(const CreateBlobContainerOptions& options)
BlobContainerInfo BlobContainerClient::Create(const CreateBlobContainerOptions& options) const
{
BlobRestClient::Container::CreateOptions protocolLayerOptions;
protocolLayerOptions.AccessType = options.AccessType;
@ -132,16 +132,17 @@ namespace Azure { namespace Storage { namespace Blobs {
options.Context, *m_pipeline, m_ContainerUri.to_string(), protocolLayerOptions);
}
BasicResponse BlobContainerClient::Delete(const DeleteBlobContainerOptions& options)
BasicResponse BlobContainerClient::Delete(const DeleteBlobContainerOptions& options) const
{
unused(options);
BlobRestClient::Container::DeleteOptions protocolLayerOptions;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
return BlobRestClient::Container::Delete(
options.Context, *m_pipeline, m_ContainerUri.to_string(), protocolLayerOptions);
}
BlobContainerProperties BlobContainerClient::GetProperties(
const GetBlobContainerPropertiesOptions& options)
const GetBlobContainerPropertiesOptions& options) const
{
unused(options);
BlobRestClient::Container::GetPropertiesOptions protocolLayerOptions;
@ -151,16 +152,16 @@ namespace Azure { namespace Storage { namespace Blobs {
BlobContainerInfo BlobContainerClient::SetMetadata(
std::map<std::string, std::string> metadata,
SetBlobContainerMetadataOptions options)
SetBlobContainerMetadataOptions options) const
{
unused(options);
BlobRestClient::Container::SetMetadataOptions protocolLayerOptions;
protocolLayerOptions.Metadata = metadata;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
return BlobRestClient::Container::SetMetadata(
options.Context, *m_pipeline, m_ContainerUri.to_string(), protocolLayerOptions);
}
BlobsFlatSegment BlobContainerClient::ListBlobs(const ListBlobsOptions& options)
BlobsFlatSegment BlobContainerClient::ListBlobs(const ListBlobsOptions& options) const
{
BlobRestClient::Container::ListBlobsOptions protocolLayerOptions;
protocolLayerOptions.Prefix = options.Prefix;

View File

@ -0,0 +1,154 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "blobs/blob_service_client.hpp"
#include "common/common_headers_request_policy.hpp"
#include "common/shared_key_policy.hpp"
#include "common/storage_common.hpp"
#include "http/curl/curl.hpp"
namespace Azure { namespace Storage { namespace Blobs {
BlobServiceClient BlobServiceClient::CreateFromConnectionString(
const std::string& connectionString,
const BlobServiceClientOptions& options)
{
auto parsedConnectionString = ParseConnectionString(connectionString);
std::string accountName;
std::string accountKey;
std::string blobEndpoint;
std::string EndpointSuffix;
std::string defaultEndpointsProtocol = ".core.windows.net";
auto ite = parsedConnectionString.find("AccountName");
if (ite != parsedConnectionString.end())
{
accountName = ite->second;
}
ite = parsedConnectionString.find("AccountKey");
if (ite != parsedConnectionString.end())
{
accountKey = ite->second;
}
ite = parsedConnectionString.find("BlobEndpoint");
if (ite != parsedConnectionString.end())
{
blobEndpoint = ite->second;
}
ite = parsedConnectionString.find("EndpointSuffix");
if (ite != parsedConnectionString.end())
{
EndpointSuffix = ite->second;
}
ite = parsedConnectionString.find("DefaultEndpointsProtocol");
if (ite != parsedConnectionString.end())
{
defaultEndpointsProtocol = ite->second;
}
UrlBuilder builder;
builder.SetScheme(defaultEndpointsProtocol);
if (!blobEndpoint.empty())
{
builder = UrlBuilder(blobEndpoint);
}
else if (!accountName.empty())
{
builder.SetHost(accountName + ".blob." + EndpointSuffix);
}
else
{
throw std::runtime_error("invalid connection string");
}
auto credential = std::make_shared<SharedKeyCredential>(accountName, accountKey);
return BlobServiceClient(builder.to_string(), credential, options);
}
BlobServiceClient::BlobServiceClient(
const std::string& serviceUri,
std::shared_ptr<SharedKeyCredential> credential,
const BlobServiceClientOptions& options)
: m_serviceUrl(serviceUri)
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
for (const auto& p : options.policies)
{
policies.emplace_back(std::unique_ptr<Azure::Core::Http::HttpPolicy>(p->Clone()));
}
policies.emplace_back(std::make_unique<CommonHeadersRequestPolicy>());
policies.emplace_back(std::make_unique<SharedKeyPolicy>(credential));
policies.emplace_back(std::make_unique<Azure::Core::Http::TransportPolicy>(
std::make_shared<Azure::Core::Http::CurlTransport>()));
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobServiceClient::BlobServiceClient(
const std::string& serviceUri,
std::shared_ptr<TokenCredential> credential,
const BlobServiceClientOptions& options)
: m_serviceUrl(serviceUri)
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
for (const auto& p : options.policies)
{
policies.emplace_back(std::unique_ptr<Azure::Core::Http::HttpPolicy>(p->Clone()));
}
policies.emplace_back(std::make_unique<CommonHeadersRequestPolicy>());
// not implemented yet
unused(credential);
policies.emplace_back(std::make_unique<Azure::Core::Http::TransportPolicy>(
std::make_shared<Azure::Core::Http::CurlTransport>()));
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
BlobServiceClient::BlobServiceClient(
const std::string& serviceUri,
const BlobServiceClientOptions& options)
: m_serviceUrl(serviceUri)
{
std::vector<std::unique_ptr<Azure::Core::Http::HttpPolicy>> policies;
for (const auto& p : options.policies)
{
policies.emplace_back(std::unique_ptr<Azure::Core::Http::HttpPolicy>(p->Clone()));
}
policies.emplace_back(std::make_unique<CommonHeadersRequestPolicy>());
policies.emplace_back(std::make_unique<Azure::Core::Http::TransportPolicy>(
std::make_shared<Azure::Core::Http::CurlTransport>()));
m_pipeline = std::make_shared<Azure::Core::Http::HttpPipeline>(policies);
}
ListContainersSegment BlobServiceClient::ListBlobContainersSegment(
const ListBlobContainersOptions& options) const
{
BlobRestClient::Service::ListBlobContainersOptions protocolLayerOptions;
protocolLayerOptions.Prefix = options.Prefix;
protocolLayerOptions.Marker = options.Marker;
protocolLayerOptions.MaxResults = options.MaxResults;
protocolLayerOptions.IncludeMetadata = ListBlobContainersIncludeOption::None;
for (auto i : options.Include)
{
if (i == ListBlobContainersIncludeOption::Metadata)
{
protocolLayerOptions.IncludeMetadata = i;
}
}
return BlobRestClient::Service::ListBlobContainers(
options.Context, *m_pipeline, m_serviceUrl.to_string(), protocolLayerOptions);
}
UserDelegationKey BlobServiceClient::GetUserDelegationKey(
const std::string& expiresOn,
const GetUserDelegationKeyOptions& options) const
{
BlobRestClient::Service::GetUserDelegationKeyOptions protocolLayerOptions;
protocolLayerOptions.StartsOn = options.StartsOn;
protocolLayerOptions.ExpiresOn = expiresOn;
return BlobRestClient::Service::GetUserDelegationKey(
options.Context, *m_pipeline, m_serviceUrl.to_string(), protocolLayerOptions);
}
}}} // namespace Azure::Storage::Blobs

View File

@ -43,7 +43,7 @@ namespace Azure { namespace Storage { namespace Blobs {
BlockBlobClient::BlockBlobClient(BlobClient blobClient) : BlobClient(std::move(blobClient)) {}
BlockBlobClient BlockBlobClient::WithSnapshot(const std::string& snapshot)
BlockBlobClient BlockBlobClient::WithSnapshot(const std::string& snapshot) const
{
BlockBlobClient newClient(*this);
if (snapshot.empty())
@ -60,16 +60,19 @@ namespace Azure { namespace Storage { namespace Blobs {
BlobContentInfo BlockBlobClient::Upload(
// TODO: We don't have BodyStream for now.
std::vector<uint8_t> content,
const UploadBlobOptions& options)
const UploadBlobOptions& options) const
{
BlobRestClient::BlockBlob::UploadOptions protocolLayerOptions;
protocolLayerOptions.BodyBuffer = &content;
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.ContentCRC64 = options.ContentCRC64;
protocolLayerOptions.BlobType = BlobType::BlockBlob;
protocolLayerOptions.Properties = options.Properties;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.Tier = options.Tier;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::BlockBlob::Upload(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
@ -78,7 +81,7 @@ namespace Azure { namespace Storage { namespace Blobs {
const std::string& blockId,
// TODO: We don't have BodyStream for now.
std::vector<uint8_t> content,
const StageBlockOptions& options)
const StageBlockOptions& options) const
{
BlobRestClient::BlockBlob::StageBlockOptions protocolLayerOptions;
protocolLayerOptions.BodyBuffer = &content;
@ -89,23 +92,68 @@ namespace Azure { namespace Storage { namespace Blobs {
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlockInfo BlockBlobClient::StageBlockFromUri(
const std::string& blockId,
const std::string& sourceUri,
const StageBlockFromUriOptions& options) const
{
BlobRestClient::BlockBlob::StageBlockFromUriOptions protocolLayerOptions;
protocolLayerOptions.BlockId = blockId;
protocolLayerOptions.SourceUri = sourceUri;
if (options.SourceOffset != std::numeric_limits<decltype(options.SourceOffset)>::max())
{
if (options.SourceLength == 0)
{
protocolLayerOptions.SourceRange = std::make_pair(
options.SourceOffset, std::numeric_limits<decltype(options.SourceOffset)>::max());
}
else
{
protocolLayerOptions.SourceRange
= std::make_pair(options.SourceOffset, options.SourceOffset + options.SourceLength - 1);
}
}
else
{
protocolLayerOptions.SourceRange
= std::make_pair(std::numeric_limits<uint64_t>::max(), uint64_t(0));
}
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.ContentCRC64 = options.ContentCRC64;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.SourceIfModifiedSince = options.SourceIfModifiedSince;
protocolLayerOptions.SourceIfUnmodifiedSince = options.SourceIfUnmodifiedSince;
protocolLayerOptions.SourceIfMatch = options.SourceIfMatch;
protocolLayerOptions.SourceIfNoneMatch = options.SourceIfNoneMatch;
return BlobRestClient::BlockBlob::StageBlockFromUri(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobContentInfo BlockBlobClient::CommitBlockList(
const std::vector<std::pair<BlockType, std::string>>& blockIds,
const CommitBlockListOptions& options)
const CommitBlockListOptions& options) const
{
BlobRestClient::BlockBlob::CommitBlockListOptions protocolLayerOptions;
protocolLayerOptions.BlockList = blockIds;
protocolLayerOptions.Properties = options.Properties;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.Tier = options.Tier;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::BlockBlob::CommitBlockList(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobBlockListInfo BlockBlobClient::GetBlockList(const GetBlockListOptions& options)
BlobBlockListInfo BlockBlobClient::GetBlockList(const GetBlockListOptions& options) const
{
BlobRestClient::BlockBlob::GetBlockListOptions protocolLayerOptions;
protocolLayerOptions.ListType = options.ListType;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::BlockBlob::GetBlockList(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}

View File

@ -0,0 +1,178 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "blobs/page_blob_client.hpp"
#include "common/storage_common.hpp"
namespace Azure { namespace Storage { namespace Blobs {
PageBlobClient PageBlobClient::CreateFromConnectionString(
const std::string& connectionString,
const std::string& containerName,
const std::string& blobName,
const PageBlobClientOptions& options)
{
PageBlobClient newClient(
BlobClient::CreateFromConnectionString(connectionString, containerName, blobName, options));
return newClient;
}
PageBlobClient::PageBlobClient(
const std::string& blobUri,
std::shared_ptr<SharedKeyCredential> credential,
const PageBlobClientOptions& options)
: BlobClient(blobUri, std::move(credential), options)
{
}
PageBlobClient::PageBlobClient(
const std::string& blobUri,
std::shared_ptr<TokenCredential> credential,
const PageBlobClientOptions& options)
: BlobClient(blobUri, std::move(credential), options)
{
}
PageBlobClient::PageBlobClient(const std::string& blobUri, const PageBlobClientOptions& options)
: BlobClient(blobUri, options)
{
}
PageBlobClient::PageBlobClient(BlobClient blobClient) : BlobClient(std::move(blobClient)) {}
PageBlobClient PageBlobClient::WithSnapshot(const std::string& snapshot) const
{
PageBlobClient newClient(*this);
if (snapshot.empty())
{
newClient.m_blobUrl.RemoveQuery("snapshot");
}
else
{
newClient.m_blobUrl.AppendQuery("snapshot", snapshot);
}
return newClient;
}
BlobContentInfo PageBlobClient::Create(
uint64_t blobContentLength,
const CreatePageBlobOptions& options)
{
BlobRestClient::PageBlob::CreateOptions protocolLayerOptions;
protocolLayerOptions.BlobContentLength = blobContentLength;
protocolLayerOptions.SequenceNumber = options.SequenceNumber;
protocolLayerOptions.Properties = options.Properties;
protocolLayerOptions.Metadata = options.Metadata;
protocolLayerOptions.Tier = options.Tier;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::Create(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
PageInfo PageBlobClient::UploadPages(
std::vector<uint8_t> content,
uint64_t offset,
const UploadPagesOptions& options)
{
BlobRestClient::PageBlob::UploadPagesOptions protocolLayerOptions;
protocolLayerOptions.BodyBuffer = &content;
protocolLayerOptions.Range = std::make_pair(offset, offset + content.size() - 1);
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.ContentCRC64 = options.ContentCRC64;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::UploadPages(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
PageInfo PageBlobClient::UploadPagesFromUri(
std::string sourceUri,
uint64_t sourceOffset,
uint64_t sourceLength,
uint64_t destinationoffset,
const UploadPagesFromUriOptions& options)
{
BlobRestClient::PageBlob::UploadPagesFromUriOptions protocolLayerOptions;
protocolLayerOptions.SourceUri = sourceUri;
protocolLayerOptions.SourceRange
= std::make_pair(sourceOffset, sourceOffset + sourceLength - 1);
protocolLayerOptions.Range
= std::make_pair(destinationoffset, destinationoffset + sourceLength - 1);
protocolLayerOptions.ContentMD5 = options.ContentMD5;
protocolLayerOptions.ContentCRC64 = options.ContentCRC64;
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::UploadPagesFromUri(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
PageInfo PageBlobClient::ClearPages(
uint64_t offset,
uint64_t length,
const ClearPagesOptions& options)
{
BlobRestClient::PageBlob::ClearPagesOptions protocolLayerOptions;
protocolLayerOptions.Range = std::make_pair(offset, offset + length - 1);
protocolLayerOptions.LeaseId = options.LeaseId;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::ClearPages(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
PageBlobInfo PageBlobClient::Resize(
uint64_t blobContentLength,
const ResizePageBlobOptions& options)
{
BlobRestClient::PageBlob::ResizeOptions protocolLayerOptions;
protocolLayerOptions.BlobContentLength = blobContentLength;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::Resize(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
PageRangesInfo PageBlobClient::GetPageRanges(const GetPageRangesOptions& options)
{
BlobRestClient::PageBlob::GetPageRangesOptions protocolLayerOptions;
protocolLayerOptions.PreviousSnapshot = options.PreviousSnapshot;
protocolLayerOptions.PreviousSnapshotUrl = options.PreviousSnapshotUrl;
protocolLayerOptions.Range
= std::make_pair(options.Offset, options.Offset + options.Length - 1);
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::GetPageRanges(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
BlobCopyInfo PageBlobClient::StartCopyIncremental(
const std::string& sourceUri,
const IncrementalCopyPageBlobOptions& options)
{
BlobRestClient::PageBlob::CopyIncrementalOptions protocolLayerOptions;
protocolLayerOptions.CopySource = sourceUri;
protocolLayerOptions.IfModifiedSince = options.IfModifiedSince;
protocolLayerOptions.IfUnmodifiedSince = options.IfUnmodifiedSince;
protocolLayerOptions.IfMatch = options.IfMatch;
protocolLayerOptions.IfNoneMatch = options.IfNoneMatch;
return BlobRestClient::PageBlob::CopyIncremental(
options.Context, *m_pipeline, m_blobUrl.to_string(), protocolLayerOptions);
}
}}} // namespace Azure::Storage::Blobs

View File

@ -31,7 +31,7 @@ namespace Azure { namespace Storage {
AlgorithmProviderInstance()
{
NTSTATUS status = BCryptOpenAlgorithmProvider(
&Handle, BCRYPT_SHA256_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
&Handle, BCRYPT_SHA256_ALGORITHM, nullptr, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptOpenAlgorithmProvider failed");
@ -41,7 +41,7 @@ namespace Azure { namespace Storage {
status = BCryptGetProperty(
Handle,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&objectLength,
reinterpret_cast<PBYTE>(&objectLength),
sizeof(objectLength),
&dataLength,
0);
@ -52,7 +52,12 @@ namespace Azure { namespace Storage {
ContextSize = objectLength;
DWORD hashLength = 0;
status = BCryptGetProperty(
Handle, BCRYPT_HASH_LENGTH, (PBYTE)&hashLength, sizeof(hashLength), &dataLength, 0);
Handle,
BCRYPT_HASH_LENGTH,
reinterpret_cast<PBYTE>(&hashLength),
sizeof(hashLength),
&dataLength,
0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptGetProperty failed");
@ -72,17 +77,21 @@ namespace Azure { namespace Storage {
NTSTATUS status = BCryptCreateHash(
AlgorithmProvider.Handle,
&hashHandle,
(PUCHAR)context.data(),
(ULONG)context.size(),
(PUCHAR)key.data(),
(ULONG)key.length(),
reinterpret_cast<PUCHAR>(&context[0]),
static_cast<ULONG>(context.size()),
reinterpret_cast<PUCHAR>(const_cast<char*>(&key[0])),
static_cast<ULONG>(key.length()),
0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptCreateHash failed");
}
status = BCryptHashData(hashHandle, (PBYTE)text.data(), (ULONG)text.length(), 0);
status = BCryptHashData(
hashHandle,
reinterpret_cast<PBYTE>(const_cast<char*>(&text[0])),
static_cast<ULONG>(text.length()),
0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptHashData failed");
@ -90,7 +99,8 @@ namespace Azure { namespace Storage {
std::string hash;
hash.resize(AlgorithmProvider.HashLength);
status = BCryptFinishHash(hashHandle, (PUCHAR)hash.data(), (ULONG)hash.length(), 0);
status = BCryptFinishHash(
hashHandle, reinterpret_cast<PUCHAR>(&hash[0]), static_cast<ULONG>(hash.length()), 0);
if (!BCRYPT_SUCCESS(status))
{
throw std::runtime_error("BCryptFinishHash failed");
@ -105,15 +115,15 @@ namespace Azure { namespace Storage {
{
std::string encoded;
// According to RFC 4648, the encoded length should be ceiling(n / 3) * 4
DWORD encodedLength = DWORD((text.length() + 2) / 3 * 4);
DWORD encodedLength = static_cast<DWORD>((text.length() + 2) / 3 * 4);
encoded.resize(encodedLength);
CryptBinaryToStringA(
(BYTE*)text.data(),
(DWORD)text.length(),
reinterpret_cast<const BYTE*>(text.data()),
static_cast<DWORD>(text.length()),
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF,
(LPSTR)encoded.data(),
(DWORD*)&encodedLength);
static_cast<LPSTR>(&encoded[0]),
&encodedLength);
return encoded;
}
@ -128,12 +138,12 @@ namespace Azure { namespace Storage {
CryptStringToBinaryA(
text.data(),
(DWORD)text.length(),
static_cast<DWORD>(text.length()),
CRYPT_STRING_BASE64 | CRYPT_STRING_STRICT,
(BYTE*)decoded.data(),
reinterpret_cast<BYTE*>(&decoded[0]),
&decodedLength,
NULL,
NULL);
nullptr,
nullptr);
decoded.resize(decodedLength);
return decoded;
}
@ -147,10 +157,10 @@ namespace Azure { namespace Storage {
HMAC(
EVP_sha256(),
key.data(),
(int)key.length(),
(const unsigned char*)text.data(),
static_cast<int>(key.length()),
reinterpret_cast<const unsigned char*>(text.data()),
text.length(),
(unsigned char*)&hash[0],
reinterpret_cast<unsigned char*>(&hash[0]),
&hashLength);
return std::string(hash, hashLength);
@ -161,7 +171,7 @@ namespace Azure { namespace Storage {
BIO* bio = BIO_new(BIO_s_mem());
bio = BIO_push(BIO_new(BIO_f_base64()), bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
BIO_write(bio, text.data(), (int)text.length());
BIO_write(bio, text.data(), static_cast<int>(text.length()));
BIO_flush(bio);
BUF_MEM* bufferPtr;
BIO_get_mem_ptr(bio, &bufferPtr);
@ -182,7 +192,7 @@ namespace Azure { namespace Storage {
BIO* bio = BIO_new_mem_buf(text.data(), -1);
bio = BIO_push(BIO_new(BIO_f_base64()), bio);
BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
int decodedLength = BIO_read(bio, &decoded[0], (int)text.length());
int decodedLength = BIO_read(bio, &decoded[0], static_cast<int>(text.length()));
BIO_free_all(bio);
decoded.resize(decodedLength);

View File

@ -0,0 +1,177 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// SPDX-License-Identifier: MIT
#include "common/xml_wrapper.hpp"
#include "libxml/xmlreader.h"
#include "libxml/xmlwriter.h"
#include <limits>
#include <stdexcept>
namespace Azure { namespace Storage {
struct XmlGlobalInitializer
{
XmlGlobalInitializer() { xmlInitParser(); }
~XmlGlobalInitializer() { xmlCleanupParser(); }
};
static void XmlGlobalInitialize() { static XmlGlobalInitializer globalInitializer; }
XmlReader::XmlReader(const char* data, std::size_t length)
{
XmlGlobalInitialize();
if (length > static_cast<std::size_t>(std::numeric_limits<int>::max()))
{
throw std::runtime_error("xml data too big");
}
m_reader = xmlReaderForMemory(data, static_cast<int>(length), nullptr, nullptr, 0);
if (!m_reader)
{
throw std::runtime_error("failed to parse xml");
}
}
XmlReader::~XmlReader() { xmlFreeTextReader(m_reader); }
XmlNode XmlReader::Read()
{
if (m_readingAttributes)
{
int ret = xmlTextReaderMoveToNextAttribute(m_reader);
if (ret == 1)
{
const char* name = reinterpret_cast<const char*>(xmlTextReaderName(m_reader));
const char* value = reinterpret_cast<const char*>(xmlTextReaderValue(m_reader));
return XmlNode{XmlNodeType::Attribute, name, value};
}
else if (ret == 0)
{
m_readingAttributes = false;
}
else
{
throw std::runtime_error("failed to parse xml");
}
}
int ret = xmlTextReaderRead(m_reader);
if (ret == 0)
{
return XmlNode{XmlNodeType::End};
}
if (ret != 1)
{
throw std::runtime_error("failed to parse xml");
}
int type = xmlTextReaderNodeType(m_reader);
bool is_empty = xmlTextReaderIsEmptyElement(m_reader) == 1;
bool has_value = xmlTextReaderHasValue(m_reader) == 1;
bool has_attributes = xmlTextReaderHasAttributes(m_reader) == 1;
const char* name = reinterpret_cast<const char*>(xmlTextReaderName(m_reader));
const char* value = reinterpret_cast<const char*>(xmlTextReaderValue(m_reader));
if (has_attributes)
{
m_readingAttributes = true;
}
if (type == XML_READER_TYPE_ELEMENT && is_empty)
{
return XmlNode{XmlNodeType::SelfClosingTag, name};
}
else if (type == XML_READER_TYPE_ELEMENT)
{
return XmlNode{XmlNodeType::StartTag, name};
}
else if (type == XML_READER_TYPE_END_ELEMENT)
{
return XmlNode{XmlNodeType::EndTag, name};
}
else if (type == XML_READER_TYPE_TEXT)
{
if (has_value)
{
return XmlNode{XmlNodeType::Text, nullptr, value};
}
}
else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE)
{
// silently ignore
}
else
{
throw std::runtime_error("unknown type " + std::to_string(type) + " while parsing xml");
}
return Read();
}
XmlWriter::XmlWriter()
{
XmlGlobalInitialize();
m_buffer = xmlBufferCreate();
m_writer = xmlNewTextWriterMemory(m_buffer, 0);
xmlTextWriterStartDocument(m_writer, nullptr, nullptr, nullptr);
}
XmlWriter::~XmlWriter()
{
xmlFreeTextWriter(m_writer);
xmlBufferFree(m_buffer);
}
void XmlWriter::Write(XmlNode node)
{
if (node.Type == XmlNodeType::StartTag)
{
if (!node.Value)
{
xmlTextWriterStartElement(m_writer, BAD_CAST(node.Name));
}
else
{
xmlTextWriterWriteElement(m_writer, BAD_CAST(node.Name), BAD_CAST(node.Value));
}
}
else if (node.Type == XmlNodeType::EndTag)
{
xmlTextWriterEndElement(m_writer);
}
else if (node.Type == XmlNodeType::SelfClosingTag)
{
xmlTextWriterStartElement(m_writer, BAD_CAST(node.Name));
xmlTextWriterEndElement(m_writer);
}
else if (node.Type == XmlNodeType::Text)
{
xmlTextWriterWriteString(m_writer, BAD_CAST(node.Value));
}
else if (node.Type == XmlNodeType::Attribute)
{
xmlTextWriterWriteAttribute(m_writer, BAD_CAST(node.Name), BAD_CAST(node.Value));
}
else if (node.Type == XmlNodeType::End)
{
xmlTextWriterEndDocument(m_writer);
}
else
{
throw std::runtime_error(
"unsupported XmlNode type "
+ std::to_string(static_cast<std::underlying_type<XmlNodeType>::type>(node.Type)));
}
}
std::string XmlWriter::GetDocument()
{
xmlTextWriterFlush(m_writer);
return std::string(reinterpret_cast<const char*>(m_buffer->content), m_buffer->use);
}
}} // namespace Azure::Storage