Statistics
| Branch: | Revision:

root / trunk / Pithos.Network / MD5BlockCalculator.cs @ 796a7c29

History | View | Annotate | Download (2.7 kB)

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
}