Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Implemention ShareFileStorageResource #38938

Merged
merged 11 commits into from
Sep 26, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,16 @@ public ShareFilesStorageResourceProvider(Azure.Storage.StorageSharedKeyCredentia
public partial class ShareFileStorageResourceOptions
{
public ShareFileStorageResourceOptions() { }
public bool? Archive { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareFileRequestConditions DestinationConditions { get { throw null; } set { } }
public System.Collections.Generic.IDictionary<string, string> DirectoryMetadata { get { throw null; } set { } }
public Azure.Storage.DownloadTransferValidationOptions DownloadTransferValidationOptions { get { throw null; } set { } }
public System.Collections.Generic.IDictionary<string, string> FileMetadata { get { throw null; } set { } }
public string FilePermissions { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareFileHttpHeaders HttpHeaders { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareProtocols? Protocols { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.FileSmbProperties SmbProperties { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareFileRequestConditions SourceConditions { get { throw null; } set { } }
public Azure.Storage.UploadTransferValidationOptions UploadTransferValidationOptions { get { throw null; } set { } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,16 @@ public ShareFilesStorageResourceProvider(Azure.Storage.StorageSharedKeyCredentia
public partial class ShareFileStorageResourceOptions
{
public ShareFileStorageResourceOptions() { }
public bool? Archive { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareFileRequestConditions DestinationConditions { get { throw null; } set { } }
public System.Collections.Generic.IDictionary<string, string> DirectoryMetadata { get { throw null; } set { } }
public Azure.Storage.DownloadTransferValidationOptions DownloadTransferValidationOptions { get { throw null; } set { } }
public System.Collections.Generic.IDictionary<string, string> FileMetadata { get { throw null; } set { } }
public string FilePermissions { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareFileHttpHeaders HttpHeaders { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareProtocols? Protocols { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.FileSmbProperties SmbProperties { get { throw null; } set { } }
public Azure.Storage.Files.Shares.Models.ShareFileRequestConditions SourceConditions { get { throw null; } set { } }
public Azure.Storage.UploadTransferValidationOptions UploadTransferValidationOptions { get { throw null; } set { } }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
</Project>
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(RequiredTargetFrameworks);net6.0</TargetFrameworks>
<IncludeGeneratorSharedCode>true</IncludeGeneratorSharedCode>
</PropertyGroup>
<PropertyGroup>
<AssemblyTitle>Microsoft Azure.Storage.DataMovement.Blobs client library</AssemblyTitle>
<AssemblyTitle>Microsoft Azure.Storage.DataMovement.Files.Shares client library</AssemblyTitle>
<Version>12.0.0-beta.1</Version>
<DefineConstants>FileDataMovementSDK;$(DefineConstants)</DefineConstants>
<DefineConstants>ShareDataMovementSDK;$(DefineConstants)</DefineConstants>
<PackageTags>Microsoft Azure Storage DataMovement, DataMovement, Microsoft, Azure, StorageScalable, azureofficial</PackageTags>
<Description>
This client library enables working with the Microsoft Azure Storage services which include the blob and file services for storing binary and text data, and the queue service for storing messages that may be accessed by a client.
Expand All @@ -32,6 +32,8 @@
<Compile Include="$(AzureCoreSharedSources)SyncAsyncEventHandlerExtensions.cs" LinkBase="Shared\Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(AzureStorageDataMovementSharedSources)DataMovementConstants.cs" LinkBase="Shared\DataMovement" />
<Compile Include="$(AzureStorageDataMovementSharedSources)StorageResourceItemInternal.cs" LinkBase="Shared\DataMovement" />
<Compile Include="$(AzureStorageDataMovementSharedSources)StorageResourceContainerInternal.cs" LinkBase="Shared\DataMovement" />
</ItemGroup>
<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text;

namespace Azure.Storage.DataMovement.Files.Shares
{
internal class DataMovementShareConstants
{
public const int KB = 1024;
public const int MB = KB * 1024;

internal const int MaxRange = 4 * MB;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using Azure.Storage.Files.Shares.Models;

namespace Azure.Storage.DataMovement.Files.Shares
{
internal static partial class DataMovementSharesExtensions
{
internal static ShareFileUploadOptions ToShareFileUploadOptions(
this ShareFileStorageResourceOptions options)
=> new()
{
Conditions = options?.DestinationConditions,
TransferValidation = options?.UploadTransferValidationOptions,
};

internal static ShareFileUploadRangeOptions ToShareFileUploadRangeOptions(
this ShareFileStorageResourceOptions options)
=> new()
{
Conditions = options?.DestinationConditions,
TransferValidation = options?.UploadTransferValidationOptions,
};

internal static ShareFileUploadRangeFromUriOptions ToShareFileUploadRangeFromUriOptions(
this ShareFileStorageResourceOptions options)
=> new()
{
Conditions = options?.DestinationConditions,
};

internal static StorageResourceProperties ToStorageResourceProperties(
this ShareFileProperties properties)
=> new(
amnguye marked this conversation as resolved.
Show resolved Hide resolved
lastModified: properties.LastModified,
createdOn: properties?.SmbProperties?.FileCreatedOn ?? default,
metadata: properties?.Metadata,
copyCompletedOn: properties.CopyCompletedOn,
copyStatusDescription: properties?.CopyStatusDescription,
copyId: properties?.CopyId,
copyProgress: properties?.CopyProgress,
copySource: new Uri(properties?.CopySource),
contentLength: properties.ContentLength,
contentType: properties?.ContentType,
eTag: properties.ETag,
contentHash: properties?.ContentHash,
blobSequenceNumber: default,
blobCommittedBlockCount: default,
isServerEncrypted: properties.IsServerEncrypted,
encryptionKeySha256: default,
encryptionScope: default,
versionId: default,
isLatestVersion: default,
expiresOn: default,
lastAccessed: default);

internal static ShareFileDownloadOptions ToShareFileDownloadOptions(
this ShareFileStorageResourceOptions options,
HttpRange range)
=> new()
{
Range = range,
Conditions = options?.SourceConditions,
TransferValidation = options?.DownloadTransferValidationOptions,
};

internal static StorageResourceReadStreamResult ToStorageResourceReadStreamResult(
this ShareFileDownloadInfo info)
=> new(
content: info?.Content,
contentRange: info?.Details.ContentRange,
acceptRanges: info?.Details.AcceptRanges,
rangeContentHash: info?.Details.FileContentHash,
properties: info?.Details.ToStorageResourceProperties());

private static StorageResourceProperties ToStorageResourceProperties(
this ShareFileDownloadDetails details)
=> new(
lastModified: details.LastModified,
createdOn: details.SmbProperties.FileCreatedOn ?? default,
metadata: details.Metadata,
copyCompletedOn: details.CopyCompletedOn,
copyStatusDescription: details.CopyStatusDescription,
copyId: details.CopyId,
copyProgress: details.CopyProgress,
copySource: details.CopySource,
contentLength: details.ContentRange.Length,
contentType: default,
eTag: details.ETag,
contentHash: default,
blobSequenceNumber: default,
blobCommittedBlockCount: default,
isServerEncrypted: details.IsServerEncrypted,
encryptionKeySha256: default,
encryptionScope: default,
versionId: default,
isLatestVersion: default,
expiresOn: default,
lastAccessed: default);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ protected override StorageResourceItem GetStorageResourceReference(string path)
dir = dir.GetSubdirectoryClient(pathSegment);
}
ShareFileClient file = dir.GetFileClient(pathSegments.Last());
return new ShareFileStorageResourceItem(file, ResourceOptions);
return new ShareFileStorageResource(file, ResourceOptions);
}

protected override async IAsyncEnumerable<StorageResource> GetStorageResourcesAsync(
Expand All @@ -44,7 +44,7 @@ protected override async IAsyncEnumerable<StorageResource> GetStorageResourcesAs
await foreach (ShareFileClient client in PathScanner.ScanFilesAsync(
ShareDirectoryClient, cancellationToken).ConfigureAwait(false))
{
yield return new ShareFileStorageResourceItem(client, ResourceOptions);
yield return new ShareFileStorageResource(client, ResourceOptions);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;

namespace Azure.Storage.DataMovement.Files.Shares
{
internal class ShareFileStorageResource : StorageResourceItemInternal
{
internal long? _length;
internal readonly ShareFileStorageResourceOptions _options;
internal ETag? _etagDownloadLock = default;

internal ShareFileClient ShareFileClient { get; }

public override Uri Uri => ShareFileClient.Uri;

protected override string ResourceId => "ShareFile";

protected override DataTransferOrder TransferType => DataTransferOrder.Sequential;

protected override long MaxChunkSize => DataMovementShareConstants.MaxRange;

protected override long? Length => _length;

public ShareFileStorageResource(
ShareFileClient fileClient,
ShareFileStorageResourceOptions options = default)
{
ShareFileClient = fileClient;
_options = options;
}

/// <summary>
/// Internal Constructor for constructing the resource retrieved by a GetStorageResources.
/// </summary>
/// <param name="fileClient">The blob client which will service the storage resource operations.</param>
/// <param name="length">The content length of the blob.</param>
/// <param name="etagLock">Preset etag to lock on for reads.</param>
/// <param name="options">Options for the storage resource. See <see cref="ShareFileStorageResourceOptions"/>.</param>
internal ShareFileStorageResource(
ShareFileClient fileClient,
long? length,
ETag? etagLock,
ShareFileStorageResourceOptions options = default)
: this(fileClient, options)
{
_length = length;
_etagDownloadLock = etagLock;
}

protected override Task CompleteTransferAsync(
bool overwrite,
CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
return Task.CompletedTask;
}

protected override async Task CopyBlockFromUriAsync(
StorageResourceItem sourceResource,
HttpRange range,
bool overwrite,
long completeLength,
StorageResourceCopyFromUriOptions options = null,
CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
await ShareFileClient.UploadRangeFromUriAsync(
sourceUri: sourceResource.Uri,
range: range,
sourceRange: range,
options: _options.ToShareFileUploadRangeFromUriOptions(),
cancellationToken: cancellationToken).ConfigureAwait(false);
}

protected override async Task CopyFromStreamAsync(
Stream stream,
long streamLength,
bool overwrite,
long completeLength,
StorageResourceWriteToOffsetOptions options = null,
CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);

long position = options?.Position != default ? options.Position.Value : 0;
if ((streamLength == completeLength) && position == 0)
{
// Default to Upload
await ShareFileClient.UploadAsync(
stream,
_options.ToShareFileUploadOptions(),
cancellationToken: cancellationToken).ConfigureAwait(false);
return;
}

// Otherwise upload the Range
await ShareFileClient.UploadRangeAsync(
new HttpRange(position, streamLength),
stream,
_options.ToShareFileUploadRangeOptions(),
cancellationToken).ConfigureAwait(false);
}

protected override async Task CopyFromUriAsync(
StorageResourceItem sourceResource,
bool overwrite,
long completeLength,
StorageResourceCopyFromUriOptions options = null,
CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
await ShareFileClient.UploadRangeFromUriAsync(
sourceUri: sourceResource.Uri,
range: new HttpRange(0, completeLength),
sourceRange: new HttpRange(0, completeLength),
options: _options.ToShareFileUploadRangeFromUriOptions(),
cancellationToken: cancellationToken).ConfigureAwait(false);
}

protected override async Task<bool> DeleteIfExistsAsync(CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
return await ShareFileClient.DeleteIfExistsAsync(cancellationToken: cancellationToken).ConfigureAwait(false);
}

protected override Task<HttpAuthorization> GetCopyAuthorizationHeaderAsync(CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
// TODO: This needs an update to ShareFileClient to allow getting the Copy Authorization Token
throw new NotImplementedException();
}

protected override async Task<StorageResourceProperties> GetPropertiesAsync(CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
Response<ShareFileProperties> response = await ShareFileClient.GetPropertiesAsync(
conditions: _options?.SourceConditions,
cancellationToken: cancellationToken).ConfigureAwait(false);
// TODO: should we be grabbing the ETag here even though we can't apply it to the download.
//GrabEtag(response.GetRawResponse());
return response.Value.ToStorageResourceProperties();
}

protected override async Task<StorageResourceReadStreamResult> ReadStreamAsync(
long position = 0,
long? length = null,
CancellationToken cancellationToken = default)
{
CancellationHelper.ThrowIfCancellationRequested(cancellationToken);
Response<ShareFileDownloadInfo> response = await ShareFileClient.DownloadAsync(
_options.ToShareFileDownloadOptions(new HttpRange(position, length)),
cancellationToken).ConfigureAwait(false);
return response.Value.ToStorageResourceReadStreamResult();
}

protected override StorageResourceCheckpointData GetSourceCheckpointData()
{
throw new NotImplementedException();
}

protected override StorageResourceCheckpointData GetDestinationCheckpointData()
{
throw new NotImplementedException();
}
}
}
Loading
Loading