-
Notifications
You must be signed in to change notification settings - Fork 189
Expand file tree
/
Copy pathFileDownloadMetrics.cs
More file actions
138 lines (121 loc) · 4.82 KB
/
FileDownloadMetrics.cs
File metadata and controls
138 lines (121 loc) · 4.82 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace Apache.Arrow.Adbc.Drivers.Databricks.Reader.CloudFetch
{
/// <summary>
/// Tracks timing and throughput metrics for individual file downloads.
/// Thread-safe for concurrent access.
/// </summary>
internal class FileDownloadMetrics
{
private readonly object _lock = new object();
private DateTime? _downloadEndTime;
private bool _wasCancelledAsStragler;
// Minimum elapsed time to avoid unrealistic throughput calculations
private const double MinimumElapsedSecondsForThroughput = 0.001;
/// <summary>
/// Initializes a new instance of the <see cref="FileDownloadMetrics"/> class.
/// </summary>
/// <param name="fileOffset">The file offset in the download batch.</param>
/// <param name="fileSizeBytes">The size of the file in bytes.</param>
public FileDownloadMetrics(long fileOffset, long fileSizeBytes)
{
if (fileSizeBytes <= 0)
{
throw new ArgumentOutOfRangeException(
nameof(fileSizeBytes),
fileSizeBytes,
"File size must be positive");
}
FileOffset = fileOffset;
FileSizeBytes = fileSizeBytes;
DownloadStartTime = DateTime.UtcNow;
}
/// <summary>
/// Gets the file offset in the download batch.
/// </summary>
public long FileOffset { get; }
/// <summary>
/// Gets the size of the file in bytes.
/// </summary>
public long FileSizeBytes { get; }
/// <summary>
/// Gets the time when the download started.
/// </summary>
public DateTime DownloadStartTime { get; }
/// <summary>
/// Gets the time when the download completed, or null if still in progress.
/// </summary>
public DateTime? DownloadEndTime => _downloadEndTime;
/// <summary>
/// Gets a value indicating whether the download has completed.
/// </summary>
public bool IsDownloadCompleted => _downloadEndTime.HasValue;
/// <summary>
/// Gets a value indicating whether this download was cancelled as a straggler.
/// </summary>
public bool WasCancelledAsStragler => _wasCancelledAsStragler;
/// <summary>
/// Calculates the download throughput in bytes per second.
/// Returns null if the download has not completed.
/// Thread-safe.
/// </summary>
/// <returns>The throughput in bytes per second, or null if not completed.</returns>
public double? CalculateThroughputBytesPerSecond()
{
lock (_lock)
{
if (!_downloadEndTime.HasValue)
{
return null;
}
TimeSpan elapsed = _downloadEndTime.Value - DownloadStartTime;
double elapsedSeconds = elapsed.TotalSeconds;
// Avoid division by zero for very fast downloads
if (elapsedSeconds < MinimumElapsedSecondsForThroughput)
{
elapsedSeconds = MinimumElapsedSecondsForThroughput;
}
return FileSizeBytes / elapsedSeconds;
}
}
/// <summary>
/// Marks the download as completed and records the end time.
/// Thread-safe - idempotent (can be called multiple times safely).
/// </summary>
public void MarkDownloadCompleted()
{
lock (_lock)
{
if (_downloadEndTime.HasValue) return; // Already marked
_downloadEndTime = DateTime.UtcNow;
}
}
/// <summary>
/// Marks this download as having been cancelled due to being identified as a straggler.
/// Thread-safe - idempotent.
/// </summary>
public void MarkCancelledAsStragler()
{
lock (_lock)
{
_wasCancelledAsStragler = true;
}
}
}
}