Skip to content

Commit b9ee3a0

Browse files
committed
Major refactor in ChunkedFileStream
1 parent fb449d4 commit b9ee3a0

File tree

1 file changed

+63
-36
lines changed

1 file changed

+63
-36
lines changed

Assets/PatchKit Patcher/Scripts/AppData/Remote/Downloaders/ChunkedFileStream.cs

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.IO;
33
using System.Linq;
4+
using JetBrains.Annotations;
5+
using PatchKit.Logging;
46
using PatchKit.Unity.Patcher.Debug;
57

68
namespace PatchKit.Unity.Patcher.AppData.Remote.Downloaders
@@ -12,20 +14,20 @@ namespace PatchKit.Unity.Patcher.AppData.Remote.Downloaders
1214
/// has to be predefined.
1315
///
1416
/// Usage:
15-
/// Use Write() function as usuall to write bytes. As soon as you will get false stop copying
17+
/// Use Write() function as usuall to write bytes. As soon as you will catch InvalidChunkDataException stop copying
1618
/// procedure and restart it from next byte after VerifiedLength. If you will try to write
1719
/// bytes above the limit, you will get ArgumentOutOfRangeException.
1820
/// </summary>
19-
public class ChunkedFileStream : IDisposable
21+
public sealed class ChunkedFileStream : IDisposable
2022
{
2123
[Flags]
2224
public enum WorkFlags
2325
{
2426
None = 0,
2527
PreservePreviousFile = 1
2628
}
27-
28-
private static readonly DebugLogger DebugLogger = new DebugLogger(typeof(ChunkedFileStream));
29+
30+
private readonly ILogger _logger;
2931

3032
public delegate byte[] HashFunction(byte[] buffer, int offset, int length);
3133

@@ -36,7 +38,7 @@ public enum WorkFlags
3638
private readonly byte[] _buffer;
3739
private int _bufferPos;
3840
private int _chunkIndex;
39-
private readonly FileStream _fileStream;
41+
private FileStream _fileStream;
4042

4143
private bool _disposed;
4244

@@ -60,58 +62,85 @@ public long Length
6062
get { return _fileSize; }
6163
}
6264

63-
public ChunkedFileStream(string path, long fileSize, ChunksData chunksData, HashFunction hashFunction,
65+
public ChunkedFileStream([NotNull] string path, long fileSize, ChunksData chunksData,
66+
[NotNull] HashFunction hashFunction,
6467
WorkFlags workFlags = WorkFlags.None)
6568
{
66-
Checks.ArgumentNotNullOrEmpty(path, "path");
67-
Checks.ArgumentMoreThanZero(fileSize, "fileSize");
68-
Checks.ArgumentNotNull(hashFunction, "hashFunction");
69-
70-
DebugLogger.LogConstructor();
71-
DebugLogger.LogVariable(path, "path");
72-
DebugLogger.LogVariable(fileSize, "fileSize");
69+
if (path == null) throw new ArgumentNullException("path");
70+
if (fileSize <= 0) throw new ArgumentOutOfRangeException("fileSize");
71+
if (hashFunction == null) throw new ArgumentNullException("hashFunction");
7372

73+
_logger = PatcherLogManager.DefaultLogger;
7474
_fileSize = fileSize;
7575
_chunksData = chunksData;
7676
_hashFunction = hashFunction;
7777

7878
_buffer = new byte[_chunksData.ChunkSize];
7979

80-
if ((workFlags | WorkFlags.PreservePreviousFile) != 0)
80+
_logger.LogTrace("path = " + path);
81+
_logger.LogTrace("fileSize = " + fileSize);
82+
_logger.LogTrace("chunksData.ChunkSize = " + chunksData.ChunkSize);
83+
84+
bool preservePreviousFile = (workFlags | WorkFlags.PreservePreviousFile) != 0;
85+
86+
_logger.LogTrace("preservePreviousFile = " + preservePreviousFile);
87+
88+
if (preservePreviousFile)
8189
{
8290
// Often you may want to continue downloading of a file if this exists
8391
// It tries to open a file and re-download it from the verified position.
8492
// It does not check the hash of the file. It trusts that the file is already valid up to that point.
8593
// Because the only way to download the file should be using Chunked Downloader.
86-
94+
95+
_logger.LogDebug("Opening file stream...");
8796
_fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None);
8897
_fileStream.Seek(0, SeekOrigin.End); // seek and stay at the end, so we can append
8998
long currentFileSize = _fileStream.Position;
99+
_logger.LogDebug("File stream opened.");
100+
_logger.LogTrace("currentFileSize = " + currentFileSize);
101+
102+
_logger.LogDebug("Checking whether stream can append to current file...");
90103

104+
105+
if (currentFileSize == 0)
106+
{
107+
_logger.LogDebug("File is new. Append is not possible.");
108+
}
91109
// Let's make sure that file size is a multiply of chunk size.
92110
// If not, something is wrong with the file.
93-
if (currentFileSize % chunksData.ChunkSize == 0)
111+
else if (currentFileSize % chunksData.ChunkSize == 0)
94112
{
95113
_chunkIndex = (int) (currentFileSize / chunksData.ChunkSize);
114+
_logger.LogDebug(string.Format("Append is possible - starting from {0} chunk index.", _chunkIndex));
96115
}
97116
else
98117
{
99-
DebugLogger.LogWarningFormat(
100-
"File {0} size {1} is not a multiply of chunk size: {2}. Will recreate it.", path,
101-
currentFileSize, chunksData.ChunkSize);
102-
118+
_logger.LogDebug(string.Format(
119+
"File size {0} is not a multiply of chunk size: {1}. Append is not possible - recreating file.",
120+
currentFileSize,
121+
chunksData.ChunkSize));
122+
123+
_logger.LogDebug("Closing previous file stream...");
103124
_fileStream.Close();
104125
_fileStream.Dispose();
105-
106-
_fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
126+
_logger.LogDebug("Previous file stream closed.");
127+
128+
OpenNewFileStream(path);
107129
}
108130
}
109131
else
110132
{
111-
_fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
133+
OpenNewFileStream(path);
112134
}
113135
}
114136

137+
private void OpenNewFileStream(string path)
138+
{
139+
_logger.LogDebug("Opening new file stream...");
140+
_fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
141+
_logger.LogDebug("New file stream opened.");
142+
}
143+
115144
/// <summary>
116145
/// Writes buffer into the file. If false is returned, stop file transfer and resume it
117146
/// starting from VerifiedLength + 1 byte.
@@ -120,10 +149,11 @@ public ChunkedFileStream(string path, long fileSize, ChunksData chunksData, Hash
120149
/// <param name="offset"></param>
121150
/// <param name="count"></param>
122151
/// <returns></returns>
123-
public void Write(byte[] buffer, int offset, int count)
152+
public void Write([NotNull] byte[] buffer, int offset, int count)
124153
{
125-
Checks.ArgumentNotNull(buffer, "buffer");
126-
// TODO: Rest of assertions
154+
if (buffer == null) throw new ArgumentNullException("buffer");
155+
if (offset < 0) throw new ArgumentOutOfRangeException("offset");
156+
if (count < 0) throw new ArgumentOutOfRangeException("count");
127157

128158
do
129159
{
@@ -133,7 +163,7 @@ public void Write(byte[] buffer, int offset, int count)
133163
"Cannot write bytes over the file size: " + _fileSize);
134164
}
135165

136-
int copyNum = (int)Math.Min(Math.Min(count, _chunksData.ChunkSize - _bufferPos), RemainingLength);
166+
int copyNum = (int) Math.Min(Math.Min(count, _chunksData.ChunkSize - _bufferPos), RemainingLength);
137167
Array.Copy(buffer, offset, _buffer, _bufferPos, copyNum);
138168

139169
count -= copyNum;
@@ -151,7 +181,6 @@ public void Write(byte[] buffer, int offset, int count)
151181
DiscardBuffer();
152182
throw new InvalidChunkDataException("Invalid chunk data.");
153183
}
154-
155184
}
156185
} while (count > 0);
157186
}
@@ -163,15 +192,15 @@ private bool ChunkFullyInBuffer()
163192

164193
private bool BufferedChunkValid()
165194
{
166-
byte[] bufferHash = _hashFunction(_buffer, 0, (int)Math.Min(_chunksData.ChunkSize, RemainingLength));
195+
byte[] bufferHash = _hashFunction(_buffer, 0, (int) Math.Min(_chunksData.ChunkSize, RemainingLength));
167196
byte[] chunkHash = _chunksData.Chunks[_chunkIndex].Hash;
168197

169198
return bufferHash.SequenceEqual(chunkHash);
170199
}
171200

172201
private void FlushBuffer()
173202
{
174-
_fileStream.Write(_buffer, 0, (int)Math.Min(_chunksData.ChunkSize, RemainingLength));
203+
_fileStream.Write(_buffer, 0, (int) Math.Min(_chunksData.ChunkSize, RemainingLength));
175204
_bufferPos = 0;
176205
_chunkIndex++;
177206
}
@@ -192,21 +221,19 @@ public void Dispose()
192221
Dispose(false);
193222
}
194223

195-
protected virtual void Dispose(bool disposing)
224+
private void Dispose(bool disposing)
196225
{
197-
if(_disposed)
226+
if (_disposed)
198227
{
199228
return;
200229
}
201230

202-
DebugLogger.LogDispose();
203-
204-
if(disposing)
231+
if (disposing)
205232
{
206233
_fileStream.Dispose();
207234
}
208235

209236
_disposed = true;
210237
}
211238
}
212-
}
239+
}

0 commit comments

Comments
 (0)