Skip to content

Commit

Permalink
Share checkpoint schema (Azure#39556)
Browse files Browse the repository at this point in the history
* initial work

* tests and fixes

* fix csproj

* fixes

* csproj
  • Loading branch information
jaschrep-msft authored and DevArjun23 committed Nov 14, 2023
1 parent 9a99303 commit 6754e4f
Show file tree
Hide file tree
Showing 9 changed files with 403 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,15 @@
<Compile Include="$(AzureCoreSharedSources)CancellationHelper.cs" LinkBase="SharedCore" />
<Compile Include="$(AzureCoreSharedSources)SyncAsyncEventHandlerExtensions.cs" LinkBase="Shared\Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(AzureStorageSharedSources)Constants.cs" LinkBase="Shared" />
<Compile Include="$(AzureStorageSharedSources)Errors.cs" LinkBase="Shared" />
<Compile Include="$(AzureStorageSharedSources)Errors.Clients.cs" LinkBase="Shared" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(AzureStorageDataMovementSharedSources)DataMovementConstants.cs" LinkBase="Shared\DataMovement" />
<Compile Include="$(AzureStorageDataMovementSharedSources)Errors.DataMovement.cs" LinkBase="Shared\DataMovement" />
<Compile Include="$(AzureStorageDataMovementSharedSources)CheckpointerExtensions.cs" LinkBase="Shared\DataMovement" />
<Compile Include="$(AzureStorageDataMovementSharedSources)StorageResourceItemInternal.cs" LinkBase="Shared\DataMovement" />
<Compile Include="$(AzureStorageDataMovementSharedSources)StorageResourceContainerInternal.cs" LinkBase="Shared\DataMovement" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Text;
using static Azure.Storage.DataMovement.DataMovementConstants;

namespace Azure.Storage.DataMovement.Files.Shares
{
Expand All @@ -13,5 +14,33 @@ internal class DataMovementShareConstants
public const int MB = KB * 1024;

internal const int MaxRange = 4 * MB;

internal class SourceCheckpointData
{
internal const int DataSize = 0;
}

internal class DestinationCheckpointData
{
internal const int SchemaVersion = 1;

internal const int VersionIndex = 0;

internal const int ContentTypeOffsetIndex = VersionIndex + IntSizeInBytes;
internal const int ContentTypeLengthIndex = ContentTypeOffsetIndex + IntSizeInBytes;
internal const int ContentEncodingOffsetIndex = ContentTypeLengthIndex + IntSizeInBytes;
internal const int ContentEncodingLengthIndex = ContentEncodingOffsetIndex + IntSizeInBytes;
internal const int ContentLanguageOffsetIndex = ContentEncodingLengthIndex + IntSizeInBytes;
internal const int ContentLanguageLengthIndex = ContentLanguageOffsetIndex + IntSizeInBytes;
internal const int ContentDispositionOffsetIndex = ContentLanguageLengthIndex + IntSizeInBytes;
internal const int ContentDispositionLengthIndex = ContentDispositionOffsetIndex + IntSizeInBytes;
internal const int CacheControlOffsetIndex = ContentDispositionLengthIndex + IntSizeInBytes;
internal const int CacheControlLengthIndex = CacheControlOffsetIndex + IntSizeInBytes;

internal const int MetadataOffsetIndex = CacheControlLengthIndex + IntSizeInBytes;
internal const int MetadataLengthIndex = MetadataOffsetIndex + IntSizeInBytes;

internal const int VariableLengthStartIndex = MetadataLengthIndex + IntSizeInBytes;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ protected override StorageResourceCheckpointData GetSourceCheckpointData()

protected override StorageResourceCheckpointData GetDestinationCheckpointData()
{
return new ShareFileDestinationCheckpointData();
return new ShareFileDestinationCheckpointData(null, null);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,196 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.IO;
using System.Text;
using Azure.Core;
using Azure.Storage.Files.Shares.Models;
using Metadata = System.Collections.Generic.IDictionary<string, string>;

namespace Azure.Storage.DataMovement.Files.Shares
{
internal class ShareFileDestinationCheckpointData : StorageResourceCheckpointData
{
public override int Length => 0;
private const char HeaderDelimiter = Constants.CommaChar;

/// <summary>
/// Schema version.
/// </summary>
public int Version;

/// <summary>
/// The content headers for the destination blob.
/// </summary>
public ShareFileHttpHeaders ContentHeaders;
private byte[] _contentTypeBytes;
private byte[] _contentEncodingBytes;
private byte[] _contentLanguageBytes;
private byte[] _contentDispositionBytes;
private byte[] _cacheControlBytes;

/// <summary>
/// The metadata for the destination blob.
/// </summary>
public Metadata Metadata;
private byte[] _metadataBytes;

public override int Length => CalculateLength();

public ShareFileDestinationCheckpointData(
ShareFileHttpHeaders contentHeaders,
Metadata metadata)
{
Version = DataMovementShareConstants.DestinationCheckpointData.SchemaVersion;
ContentHeaders = contentHeaders;
_contentTypeBytes = ContentHeaders?.ContentType != default ? Encoding.UTF8.GetBytes(ContentHeaders.ContentType) : Array.Empty<byte>();
_contentEncodingBytes = ContentHeaders?.ContentEncoding != default ? Encoding.UTF8.GetBytes(string.Join(HeaderDelimiter.ToString(), ContentHeaders.ContentEncoding)) : Array.Empty<byte>();
_contentLanguageBytes = ContentHeaders?.ContentLanguage != default ? Encoding.UTF8.GetBytes(string.Join(HeaderDelimiter.ToString(), ContentHeaders.ContentLanguage)) : Array.Empty<byte>();
_contentDispositionBytes = ContentHeaders?.ContentDisposition != default ? Encoding.UTF8.GetBytes(ContentHeaders.ContentDisposition) : Array.Empty<byte>();
_cacheControlBytes = ContentHeaders?.CacheControl != default ? Encoding.UTF8.GetBytes(ContentHeaders.CacheControl) : Array.Empty<byte>();
Metadata = metadata;
_metadataBytes = Metadata != default ? Encoding.UTF8.GetBytes(Metadata.DictionaryToString()) : Array.Empty<byte>();
}

internal void SerializeInternal(Stream stream) => Serialize(stream);

protected override void Serialize(Stream stream)
{
Argument.AssertNotNull(stream, nameof(stream));

int currentVariableLengthIndex = DataMovementShareConstants.DestinationCheckpointData.VariableLengthStartIndex;
BinaryWriter writer = new(stream);

// Version
writer.Write(Version);

// Fixed position offset/lengths for variable length info
writer.WriteVariableLengthFieldInfo(_contentTypeBytes.Length, ref currentVariableLengthIndex);
writer.WriteVariableLengthFieldInfo(_contentEncodingBytes.Length, ref currentVariableLengthIndex);
writer.WriteVariableLengthFieldInfo(_contentLanguageBytes.Length, ref currentVariableLengthIndex);
writer.WriteVariableLengthFieldInfo(_contentDispositionBytes.Length, ref currentVariableLengthIndex);
writer.WriteVariableLengthFieldInfo(_cacheControlBytes.Length, ref currentVariableLengthIndex);
writer.WriteVariableLengthFieldInfo(_metadataBytes.Length, ref currentVariableLengthIndex);

// Variable length info
writer.Write(_contentTypeBytes);
writer.Write(_contentEncodingBytes);
writer.Write(_contentLanguageBytes);
writer.Write(_contentDispositionBytes);
writer.Write(_cacheControlBytes);
writer.Write(_metadataBytes);
}

internal static ShareFileDestinationCheckpointData Deserialize(Stream stream)
{
Argument.AssertNotNull(stream, nameof(stream));

BinaryReader reader = new BinaryReader(stream);

// Version
int version = reader.ReadInt32();
if (version != DataMovementShareConstants.DestinationCheckpointData.SchemaVersion)
{
throw Storage.Errors.UnsupportedJobSchemaVersionHeader(version.ToString());
}

// ContentType offset/length
int contentTypeOffset = reader.ReadInt32();
int contentTypeLength = reader.ReadInt32();

// ContentEncoding offset/length
int contentEncodingOffset = reader.ReadInt32();
int contentEncodingLength = reader.ReadInt32();

// ContentLanguage offset/length
int contentLanguageOffset = reader.ReadInt32();
int contentLanguageLength = reader.ReadInt32();

// ContentDisposition offset/length
int contentDispositionOffset = reader.ReadInt32();
int contentDispositionLength = reader.ReadInt32();

// CacheControl offset/length
int cacheControlOffset = reader.ReadInt32();
int cacheControlLength = reader.ReadInt32();

// Metadata offset/length
int metadataOffset = reader.ReadInt32();
int metadataLength = reader.ReadInt32();

// ContentType
string contentType = null;
if (contentTypeOffset > 0)
{
reader.BaseStream.Position = contentTypeOffset;
contentType = Encoding.UTF8.GetString(reader.ReadBytes(contentTypeLength));
}

// ContentEncoding
string contentEncoding = null;
if (contentEncodingOffset > 0)
{
reader.BaseStream.Position = contentEncodingOffset;
contentEncoding = Encoding.UTF8.GetString(reader.ReadBytes(contentEncodingLength));
}

// ContentLanguage
string contentLanguage = null;
if (contentLanguageOffset > 0)
{
reader.BaseStream.Position = contentLanguageOffset;
contentLanguage = Encoding.UTF8.GetString(reader.ReadBytes(contentLanguageLength));
}

// ContentDisposition
string contentDisposition = null;
if (contentDispositionOffset > 0)
{
reader.BaseStream.Position = contentDispositionOffset;
contentDisposition = Encoding.UTF8.GetString(reader.ReadBytes(contentDispositionLength));
}

// CacheControl
string cacheControl = null;
if (cacheControlOffset > 0)
{
reader.BaseStream.Position = cacheControlOffset;
cacheControl = Encoding.UTF8.GetString(reader.ReadBytes(cacheControlLength));
}

// Metadata
string metadataString = string.Empty;
if (metadataOffset > 0)
{
reader.BaseStream.Position = metadataOffset;
metadataString = Encoding.UTF8.GetString(reader.ReadBytes(metadataLength));
}

ShareFileHttpHeaders contentHeaders = new()
{
ContentType = contentType,
ContentEncoding = contentEncoding.Split(HeaderDelimiter),
ContentLanguage = contentLanguage.Split(HeaderDelimiter),
ContentDisposition = contentDisposition,
CacheControl = cacheControl,
};

return new(
contentHeaders,
metadataString.ToDictionary(nameof(metadataString)));
}

private int CalculateLength()
{
// Length is fixed size fields plus length of each variable length field
int length = DataMovementShareConstants.DestinationCheckpointData.VariableLengthStartIndex;
length += _contentTypeBytes.Length;
length += _contentEncodingBytes.Length;
length += _contentLanguageBytes.Length;
length += _contentDispositionBytes.Length;
length += _cacheControlBytes.Length;
length += _metadataBytes.Length;
return length;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ internal class ShareFileSourceCheckpointData : StorageResourceCheckpointData
{
public override int Length => 0;

internal void SerializeInternal(Stream stream) => Serialize(stream);

protected override void Serialize(Stream stream)
{
}

internal static ShareFileSourceCheckpointData Deserialize(Stream stream) => new();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ protected override StorageResourceCheckpointData GetSourceCheckpointData()

protected override StorageResourceCheckpointData GetDestinationCheckpointData()
{
return new ShareFileDestinationCheckpointData();
return new ShareFileDestinationCheckpointData(null, null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
</ItemGroup>
<ItemGroup>
<!-- Required Shared Source for testing -->
<Compile Include="$(AzureStorageSharedSources)Constants.cs" LinkBase="Shared" />
<Compile Include="$(AzureStorageSharedSources)Errors.cs" LinkBase="Shared" />
<Compile Include="$(AzureStorageSharedSources)Errors.Clients.cs" LinkBase="Shared" />
<Compile Include="$(AzureStorageSharedSources)StorageConnectionString.cs" LinkBase="Shared" />
<Compile Include="$(AzureStorageSharedSources)StorageVersionExtensions.cs" LinkBase="Shared\Storage" />
<Compile Include="$(AzureStorageSharedSources)SharedAccessSignatureCredentials.cs" LinkBase="Shared" />
Expand All @@ -26,8 +23,8 @@
<Compile Include="$(AzureStorageSharedTestSources)\**\*.cs" LinkBase="Shared\Storage" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\Azure.Storage.Files.Shares\tests\DisposingShare.cs" LinkBase="Shared\Storage" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\Azure.Storage.Files.Shares\tests\ShareClientTestFixtureAttribute.cs" LinkBase="Shared\Storage" />
<Compile Remove="$(AzureStorageSharedTestSources)\AzuriteFixture.cs"/>
<Compile Remove="$(AzureStorageSharedTestSources)\AzuriteNUnitFixture.cs"/>
<Compile Remove="$(AzureStorageSharedTestSources)\AzuriteFixture.cs" />
<Compile Remove="$(AzureStorageSharedTestSources)\AzuriteNUnitFixture.cs" />
<Compile Remove="$(AzureStorageSharedTestSources)\ClientSideEncryptionTestExtensions.cs" />
<Compile Remove="$(AzureStorageSharedTestSources)\StorageTestBase.SasVersion.cs" />
<Compile Remove="$(AzureStorageSharedTestSources)\TransferValidationTestBase.cs" />
Expand Down
Loading

0 comments on commit 6754e4f

Please sign in to comment.