Revision 796a7c29 trunk/Pithos.Network/MD5BlockCalculator.cs
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 |
public 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(int capacity) |
|
22 |
{ |
|
23 |
var opt = new ExecutionDataflowBlockOptions {BoundedCapacity = capacity}; |
|
24 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t),opt); |
|
25 |
} |
|
26 |
|
|
27 |
public MD5BlockCalculator() |
|
28 |
{ |
|
29 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t)); |
|
30 |
} |
|
31 |
|
|
32 |
private void ProcessBlock(Tuple<long,byte[],int> tuple) |
|
33 |
{ |
|
34 |
if (tuple.Item1 == _currentBlock) |
|
35 |
{ |
|
36 |
_hasher.TransformBlock(tuple.Item2, 0, tuple.Item3, null, 0); |
|
37 |
Interlocked.Increment(ref _currentBlock); |
|
38 |
} |
|
39 |
else |
|
40 |
{ |
|
41 |
_actionBlock.Post(tuple); |
|
42 |
} |
|
43 |
} |
|
44 |
|
|
45 |
public void PostBlock(long blockIndex,byte[] buffer,int size) |
|
46 |
{ |
|
47 |
_actionBlock.Post(Tuple.Create(blockIndex, buffer, size)); |
|
48 |
} |
|
49 |
|
|
50 |
public async Task<string> GetHash() |
|
51 |
{ |
|
52 |
_actionBlock.Complete(); |
|
53 |
await _actionBlock.Completion; |
|
54 |
Debug.Assert(_actionBlock.InputCount == 0); |
|
55 |
_hasher.TransformFinalBlock(new byte[0], 0, 0); |
|
56 |
var hash=_hasher.Hash.ToHashString(); |
|
57 |
return hash; |
|
58 |
} |
|
59 |
|
|
60 |
public void Dispose() |
|
61 |
{ |
|
62 |
Dispose(true); |
|
63 |
GC.SuppressFinalize(this); |
|
64 |
} |
|
65 |
|
|
66 |
protected virtual void Dispose(bool disposing) |
|
67 |
{ |
|
68 |
if (disposing && _hasher!=null) |
|
69 |
_hasher.Dispose(); |
|
70 |
_hasher = null; |
|
71 |
} |
|
72 |
} |
|
73 |
} |
|
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 |
using OpenSSL.Core; |
|
11 |
using OpenSSL.Crypto; |
|
12 |
|
|
13 |
|
|
14 |
namespace Pithos.Network |
|
15 |
{ |
|
16 |
public class MD5BlockCalculator:IDisposable |
|
17 |
{ |
|
18 |
private MessageDigestContext _hasher ; |
|
19 |
|
|
20 |
private ActionBlock<Tuple<long, byte[],int>> _actionBlock; |
|
21 |
|
|
22 |
private long _currentBlock = 0; |
|
23 |
|
|
24 |
public MD5BlockCalculator(int capacity) |
|
25 |
{ |
|
26 |
var opt = new ExecutionDataflowBlockOptions {BoundedCapacity = capacity}; |
|
27 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t),opt); |
|
28 |
_hasher = new MessageDigestContext(MessageDigest.CreateByName("md5")); |
|
29 |
_hasher.Init(); |
|
30 |
} |
|
31 |
|
|
32 |
public MD5BlockCalculator() |
|
33 |
{ |
|
34 |
_actionBlock=new ActionBlock<Tuple<long, byte[],int>>(t=> ProcessBlock(t)); |
|
35 |
_hasher = new MessageDigestContext(MessageDigest.CreateByName("md5")); |
|
36 |
_hasher.Init(); |
|
37 |
} |
|
38 |
|
|
39 |
private void ProcessBlock(Tuple<long,byte[],int> tuple) |
|
40 |
{ |
|
41 |
if (tuple.Item1 == _currentBlock) |
|
42 |
{ |
|
43 |
var size = tuple.Item3; |
|
44 |
|
|
45 |
var buffer= tuple.Item2; |
|
46 |
if (size == buffer.Length) |
|
47 |
{ |
|
48 |
_hasher.Update(buffer); |
|
49 |
} |
|
50 |
else |
|
51 |
{ |
|
52 |
var block = new byte[size]; |
|
53 |
Buffer.BlockCopy(buffer, 0, block, 0, size); |
|
54 |
_hasher.Update(block); |
|
55 |
} |
|
56 |
Interlocked.Increment(ref _currentBlock); |
|
57 |
} |
|
58 |
else |
|
59 |
{ |
|
60 |
_actionBlock.Post(tuple); |
|
61 |
} |
|
62 |
} |
|
63 |
|
|
64 |
public void PostBlock(long blockIndex,byte[] buffer,int size) |
|
65 |
{ |
|
66 |
_actionBlock.Post(Tuple.Create(blockIndex, buffer, size)); |
|
67 |
} |
|
68 |
|
|
69 |
public async Task<string> GetHash() |
|
70 |
{ |
|
71 |
_actionBlock.Complete(); |
|
72 |
await _actionBlock.Completion; |
|
73 |
Debug.Assert(_actionBlock.InputCount == 0); |
|
74 |
var hashBytes=_hasher.DigestFinal(); |
|
75 |
var hash=hashBytes.ToHashString(); |
|
76 |
return hash; |
|
77 |
} |
|
78 |
|
|
79 |
public void Dispose() |
|
80 |
{ |
|
81 |
Dispose(true); |
|
82 |
GC.SuppressFinalize(this); |
|
83 |
} |
|
84 |
|
|
85 |
protected virtual void Dispose(bool disposing) |
|
86 |
{ |
|
87 |
if (disposing && _hasher!=null) |
|
88 |
_hasher.Dispose(); |
|
89 |
_hasher = null; |
|
90 |
} |
|
91 |
} |
|
92 |
} |
Also available in: Unified diff