Revision db63c1ae
b/trunk/Pithos.Network/BlockHashAlgorithms.cs | ||
---|---|---|
230 | 230 |
return _bufferMgr; |
231 | 231 |
} |
232 | 232 |
|
233 |
public static async Task<ConcurrentDictionary<long, byte[]>> CalculateBlockHashesInPlacePFor(FileStream stream, int blockSize, string algorithm, int parallelism,IProgress<double> progress )
|
|
233 |
public static async Task<ConcurrentDictionary<long, byte[]>> CalculateBlockHashesInPlacePFor(FileStream stream, int blockSize, string algorithm, int parallelism, Action<long, byte[], int> postAction, IProgress<double> progress)
|
|
234 | 234 |
{ |
235 | 235 |
if (stream == null) |
236 | 236 |
throw new ArgumentNullException("stream"); |
... | ... | |
273 | 273 |
int bufIdx = 0; |
274 | 274 |
long index = 0; |
275 | 275 |
|
276 |
long block = 0; |
|
276 | 277 |
|
277 | 278 |
while ((read = await stream.ReadAsync(buffer[bufIdx], 0, blockSize).ConfigureAwait(false)) > 0) |
278 | 279 |
{ |
279 | 280 |
index += read; |
280 | 281 |
indices[bufIdx] = index; |
281 | 282 |
bufferCount[bufIdx] = read; |
283 |
postAction(block++, buffer[bufIdx], read); |
|
284 |
|
|
282 | 285 |
//If we have filled the last buffer or if we have read from the last block, |
283 | 286 |
//we can calculate the clocks in parallel |
284 | 287 |
if (bufIdx == parallelism - 1 || read < blockSize) |
... | ... | |
305 | 308 |
progress.Report((long)hashes.Count*blockSize*1.0/stream.Length); |
306 | 309 |
}); |
307 | 310 |
} |
308 |
bufIdx = (bufIdx + 1)%parallelism;
|
|
311 |
bufIdx = (bufIdx +1)%parallelism; |
|
309 | 312 |
} |
310 | 313 |
} |
311 | 314 |
finally |
b/trunk/Pithos.Network/MD5BlockCalculator.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections.Generic; |
|
3 |
using System.Diagnostics; |
|
4 |
using System.Linq; |
|
5 |
using System.Security.Cryptography; |
|
6 |
using System.Text; |
|
7 |
using System.Threading; |
|
8 |
using System.Threading.Tasks; |
|
9 |
using System.Threading.Tasks.Dataflow; |
|
10 |
|
|
11 |
namespace Pithos.Network |
|
12 |
{ |
|
13 |
class MD5BlockCalculator:IDisposable |
|
14 |
{ |
|
15 |
private HashAlgorithm _hasher = HashAlgorithm.Create("md5"); |
|
16 |
|
|
17 |
private ActionBlock<Tuple<long, byte[],int>> _actionBlock; |
|
18 |
|
|
19 |
private long _currentBlock = 0; |
|
20 |
|
|
21 |
public MD5BlockCalculator() |
|
22 |
{ |
|
23 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t)); |
|
24 |
} |
|
25 |
|
|
26 |
private void ProcessBlock(Tuple<long,byte[],int> tuple) |
|
27 |
{ |
|
28 |
if (tuple.Item1 == _currentBlock) |
|
29 |
{ |
|
30 |
_hasher.TransformBlock(tuple.Item2, 0, tuple.Item3, null, 0); |
|
31 |
Interlocked.Increment(ref _currentBlock); |
|
32 |
} |
|
33 |
else |
|
34 |
{ |
|
35 |
_actionBlock.Post(tuple); |
|
36 |
} |
|
37 |
} |
|
38 |
|
|
39 |
public void PostBlock(long blockIndex,byte[] buffer,int size) |
|
40 |
{ |
|
41 |
_actionBlock.Post(Tuple.Create(blockIndex, buffer, size)); |
|
42 |
} |
|
43 |
|
|
44 |
public async Task<string> GetHash() |
|
45 |
{ |
|
46 |
_actionBlock.Complete(); |
|
47 |
await _actionBlock.Completion; |
|
48 |
Debug.Assert(_actionBlock.InputCount == 0); |
|
49 |
_hasher.TransformFinalBlock(new byte[0], 0, 0); |
|
50 |
var hash=_hasher.Hash.ToHashString(); |
|
51 |
return hash; |
|
52 |
} |
|
53 |
|
|
54 |
public void Dispose() |
|
55 |
{ |
|
56 |
Dispose(true); |
|
57 |
GC.SuppressFinalize(this); |
|
58 |
} |
|
59 |
|
|
60 |
protected virtual void Dispose(bool disposing) |
|
61 |
{ |
|
62 |
if (disposing && _hasher!=null) |
|
63 |
_hasher.Dispose(); |
|
64 |
_hasher = null; |
|
65 |
} |
|
66 |
} |
|
67 |
} |
b/trunk/Pithos.Network/Pithos.Network.csproj | ||
---|---|---|
233 | 233 |
<Compile Include="CloudFilesClient.cs" /> |
234 | 234 |
<Compile Include="ContainerInfo.cs" /> |
235 | 235 |
<Compile Include="ICloudClient.cs" /> |
236 |
<Compile Include="MD5BlockCalculator.cs" /> |
|
236 | 237 |
<Compile Include="NoModificationInfo.cs" /> |
237 | 238 |
<Compile Include="RestClient.cs"> |
238 | 239 |
<SubType>Component</SubType> |
b/trunk/Pithos.Network/Signature.cs | ||
---|---|---|
198 | 198 |
//Calculate the hash of all blocks using a blockhash iterator |
199 | 199 |
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, blockSize, true)) |
200 | 200 |
{ |
201 |
var md5 = new MD5BlockCalculator(); |
|
202 |
Action<long, byte[], int> postAction = md5.PostBlock; |
|
201 | 203 |
//Calculate the blocks asyncrhonously |
202 |
var hashes = BlockHashAlgorithms.CalculateBlockHashesInPlacePFor(stream, blockSize, algorithm, parallelism,progress).Result; |
|
204 |
var hashes = BlockHashAlgorithms.CalculateBlockHashesInPlacePFor(stream, blockSize, algorithm, parallelism,postAction, progress).Result;
|
|
203 | 205 |
|
204 | 206 |
//And then proceed with creating and returning a TreeHash |
205 | 207 |
var length = stream.Length; |
... | ... | |
213 | 215 |
}; |
214 | 216 |
|
215 | 217 |
string fileHash; |
218 |
|
|
219 |
var md5Hash=md5.GetHash().Result; |
|
220 |
/* |
|
216 | 221 |
var hasher = HashAlgorithm.Create("MD5"); |
217 | 222 |
stream.Position = 0; |
218 |
treeHash.MD5= hasher.ComputeHash(stream).ToHashString(); |
|
223 |
*/ |
|
224 |
treeHash.MD5= md5Hash; |
|
219 | 225 |
|
220 | 226 |
return treeHash; |
221 | 227 |
} |
Also available in: Unified diff