-
Notifications
You must be signed in to change notification settings - Fork 132
/
PageBlobReader.cs
117 lines (102 loc) · 5.22 KB
/
PageBlobReader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//------------------------------------------------------------------------------
// <copyright file="PageBlobReader.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation
// </copyright>
//------------------------------------------------------------------------------
namespace Microsoft.Azure.Storage.DataMovement.TransferControllers
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.Storage.Blob;
internal sealed class PageBlobReader : RangeBasedReader
{
private readonly AzureBlobLocation sourceLocation;
private readonly CloudPageBlob pageBlob;
public PageBlobReader(
TransferScheduler scheduler,
SyncTransferController controller,
CancellationToken cancellationToken)
:base(scheduler, controller, cancellationToken)
{
this.sourceLocation = this.SharedTransferData.TransferJob.Source as AzureBlobLocation;
this.pageBlob = this.sourceLocation?.Blob as CloudPageBlob;
Debug.Assert(null != this.pageBlob, "Initializing a PageBlobReader, the source location should be a CloudPageBlob instance.");
}
protected override async Task DoFetchAttributesAsync()
{
if (this.sourceLocation.IsInstanceInfoFetched != true)
{
AccessCondition accessCondition = Utils.GenerateIfMatchConditionWithCustomerCondition(
this.sourceLocation.ETag,
this.sourceLocation.AccessCondition,
this.sourceLocation.CheckedAccessCondition);
await this.pageBlob.FetchAttributesAsync(
accessCondition,
Utils.GenerateBlobRequestOptions(this.sourceLocation.BlobRequestOptions),
Utils.GenerateOperationContext(this.Controller.TransferContext),
this.CancellationToken);
}
if (string.IsNullOrEmpty(this.sourceLocation.ETag))
{
if ((0 != this.SharedTransferData.TransferJob.CheckPoint.EntryTransferOffset)
|| (this.SharedTransferData.TransferJob.CheckPoint.TransferWindow.Any()))
{
throw new InvalidOperationException(Resources.RestartableInfoCorruptedException);
}
this.sourceLocation.ETag = this.sourceLocation.Blob.Properties.ETag;
}
else if ((this.SharedTransferData.TransferJob.CheckPoint.EntryTransferOffset > this.sourceLocation.Blob.Properties.Length)
|| (this.SharedTransferData.TransferJob.CheckPoint.EntryTransferOffset < 0))
{
throw new InvalidOperationException(Resources.RestartableInfoCorruptedException);
}
this.SharedTransferData.DisableContentMD5Validation =
null != this.sourceLocation.BlobRequestOptions ?
this.sourceLocation.BlobRequestOptions.DisableContentMD5Validation.HasValue ?
this.sourceLocation.BlobRequestOptions.DisableContentMD5Validation.Value : false : false;
this.SharedTransferData.Attributes = Utils.GenerateAttributes(this.pageBlob);
this.SharedTransferData.TotalLength = this.pageBlob.Properties.Length;
}
protected override async Task<List<Utils.Range>> DoGetRangesAsync(Utils.RangesSpan rangesSpan)
{
AccessCondition accessCondition = Utils.GenerateIfMatchConditionWithCustomerCondition(
this.sourceLocation.Blob.Properties.ETag,
this.sourceLocation.AccessCondition);
List<Utils.Range> rangeList = new List<Utils.Range>();
foreach (var pageRange in await this.pageBlob.GetPageRangesAsync(
rangesSpan.StartOffset,
rangesSpan.EndOffset - rangesSpan.StartOffset + 1,
accessCondition,
Utils.GenerateBlobRequestOptions(this.sourceLocation.BlobRequestOptions),
Utils.GenerateOperationContext(this.Controller.TransferContext),
this.CancellationToken))
{
rangeList.Add(new Utils.Range()
{
StartOffset = pageRange.StartOffset,
EndOffset = pageRange.EndOffset,
HasData = true
});
}
return rangeList;
}
protected override async Task DoDownloadRangeToStreamAsync(RangeBasedDownloadState asyncState)
{
AccessCondition accessCondition = Utils.GenerateIfMatchConditionWithCustomerCondition(
this.sourceLocation.Blob.Properties.ETag,
this.sourceLocation.AccessCondition);
await this.sourceLocation.Blob.DownloadRangeToStreamAsync(
asyncState.DownloadStream,
asyncState.StartOffset,
asyncState.Length,
accessCondition,
Utils.GenerateBlobRequestOptions(this.sourceLocation.BlobRequestOptions),
Utils.GenerateOperationContext(this.Controller.TransferContext),
this.CancellationToken);
}
}
}