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