root / trunk / Pithos.Network / BlockHashAlgorithms.cs @ 6bcdd8e2
History | View | Annotate | Download (9.3 kB)
1 | 255f5f86 | Panagiotis Kanavos | #region |
---|---|---|---|
2 | 255f5f86 | Panagiotis Kanavos | /* ----------------------------------------------------------------------- |
3 | 255f5f86 | Panagiotis Kanavos | * <copyright file="BlockHashAlgorithms.cs" company="GRNet"> |
4 | 255f5f86 | Panagiotis Kanavos | * |
5 | 255f5f86 | Panagiotis Kanavos | * Copyright 2011-2012 GRNET S.A. All rights reserved. |
6 | 255f5f86 | Panagiotis Kanavos | * |
7 | 255f5f86 | Panagiotis Kanavos | * Redistribution and use in source and binary forms, with or |
8 | 255f5f86 | Panagiotis Kanavos | * without modification, are permitted provided that the following |
9 | 255f5f86 | Panagiotis Kanavos | * conditions are met: |
10 | 255f5f86 | Panagiotis Kanavos | * |
11 | 255f5f86 | Panagiotis Kanavos | * 1. Redistributions of source code must retain the above |
12 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
13 | 255f5f86 | Panagiotis Kanavos | * disclaimer. |
14 | 255f5f86 | Panagiotis Kanavos | * |
15 | 255f5f86 | Panagiotis Kanavos | * 2. Redistributions in binary form must reproduce the above |
16 | 255f5f86 | Panagiotis Kanavos | * copyright notice, this list of conditions and the following |
17 | 255f5f86 | Panagiotis Kanavos | * disclaimer in the documentation and/or other materials |
18 | 255f5f86 | Panagiotis Kanavos | * provided with the distribution. |
19 | 255f5f86 | Panagiotis Kanavos | * |
20 | 255f5f86 | Panagiotis Kanavos | * |
21 | 255f5f86 | Panagiotis Kanavos | * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS |
22 | 255f5f86 | Panagiotis Kanavos | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
23 | 255f5f86 | Panagiotis Kanavos | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
24 | 255f5f86 | Panagiotis Kanavos | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR |
25 | 255f5f86 | Panagiotis Kanavos | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
26 | 255f5f86 | Panagiotis Kanavos | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
27 | 255f5f86 | Panagiotis Kanavos | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
28 | 255f5f86 | Panagiotis Kanavos | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
29 | 255f5f86 | Panagiotis Kanavos | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
30 | 255f5f86 | Panagiotis Kanavos | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
31 | 255f5f86 | Panagiotis Kanavos | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | 255f5f86 | Panagiotis Kanavos | * POSSIBILITY OF SUCH DAMAGE. |
33 | 255f5f86 | Panagiotis Kanavos | * |
34 | 255f5f86 | Panagiotis Kanavos | * The views and conclusions contained in the software and |
35 | 255f5f86 | Panagiotis Kanavos | * documentation are those of the authors and should not be |
36 | 255f5f86 | Panagiotis Kanavos | * interpreted as representing official policies, either expressed |
37 | 255f5f86 | Panagiotis Kanavos | * or implied, of GRNET S.A. |
38 | 255f5f86 | Panagiotis Kanavos | * </copyright> |
39 | 255f5f86 | Panagiotis Kanavos | * ----------------------------------------------------------------------- |
40 | 255f5f86 | Panagiotis Kanavos | */ |
41 | 255f5f86 | Panagiotis Kanavos | #endregion |
42 | 422c9598 | Panagiotis Kanavos | using System.Collections.Concurrent; |
43 | 422c9598 | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
44 | 422c9598 | Panagiotis Kanavos | using System.IO; |
45 | 6bcdd8e2 | Panagiotis Kanavos | using System.Reflection; |
46 | 422c9598 | Panagiotis Kanavos | using System.Security.Cryptography; |
47 | 422c9598 | Panagiotis Kanavos | using System.Threading.Tasks; |
48 | 422c9598 | Panagiotis Kanavos | using System.Threading.Tasks.Dataflow; |
49 | 422c9598 | Panagiotis Kanavos | |
50 | 422c9598 | Panagiotis Kanavos | namespace Pithos.Network |
51 | 422c9598 | Panagiotis Kanavos | { |
52 | 422c9598 | Panagiotis Kanavos | using System; |
53 | 422c9598 | Panagiotis Kanavos | using System.Collections.Generic; |
54 | 422c9598 | Panagiotis Kanavos | using System.Linq; |
55 | 422c9598 | Panagiotis Kanavos | using System.Text; |
56 | 422c9598 | Panagiotis Kanavos | |
57 | 422c9598 | Panagiotis Kanavos | /// <summary> |
58 | 422c9598 | Panagiotis Kanavos | /// TODO: Update summary. |
59 | 422c9598 | Panagiotis Kanavos | /// </summary> |
60 | 422c9598 | Panagiotis Kanavos | public static class BlockHashAlgorithms |
61 | 422c9598 | Panagiotis Kanavos | { |
62 | 6bcdd8e2 | Panagiotis Kanavos | private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
63 | 6bcdd8e2 | Panagiotis Kanavos | |
64 | 422c9598 | Panagiotis Kanavos | public static Func<FileStream, int, string, ConcurrentDictionary<int, byte[]>, int, Task<ConcurrentDictionary<int, byte[]>>> CalculateBlockHash; |
65 | 422c9598 | Panagiotis Kanavos | |
66 | 422c9598 | Panagiotis Kanavos | public static Task<ConcurrentDictionary<int, byte[]>> CalculateBlockHashesRecursiveAsync(FileStream stream, int blockSize, string algorithm, ConcurrentDictionary<int, byte[]> hashes = null, int index = 0) |
67 | 422c9598 | Panagiotis Kanavos | { |
68 | 422c9598 | Panagiotis Kanavos | if (stream == null) |
69 | 422c9598 | Panagiotis Kanavos | throw new ArgumentNullException("stream"); |
70 | 422c9598 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(algorithm)) |
71 | 422c9598 | Panagiotis Kanavos | throw new ArgumentNullException("algorithm"); |
72 | 422c9598 | Panagiotis Kanavos | if (blockSize <= 0) |
73 | 422c9598 | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero "); |
74 | 422c9598 | Panagiotis Kanavos | if (index < 0) |
75 | 422c9598 | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("index", "index must be a non-negative value"); |
76 | 422c9598 | Panagiotis Kanavos | Contract.EndContractBlock(); |
77 | 422c9598 | Panagiotis Kanavos | |
78 | 422c9598 | Panagiotis Kanavos | |
79 | 422c9598 | Panagiotis Kanavos | if (hashes == null) |
80 | 422c9598 | Panagiotis Kanavos | hashes = new ConcurrentDictionary<int, byte[]>(); |
81 | 422c9598 | Panagiotis Kanavos | |
82 | 422c9598 | Panagiotis Kanavos | var buffer = new byte[blockSize]; |
83 | 422c9598 | Panagiotis Kanavos | return stream.ReadAsync(buffer, 0, blockSize).ContinueWith(t => |
84 | 422c9598 | Panagiotis Kanavos | { |
85 | 422c9598 | Panagiotis Kanavos | var read = t.Result; |
86 | 422c9598 | Panagiotis Kanavos | |
87 | 422c9598 | Panagiotis Kanavos | var nextTask = read == blockSize |
88 | 422c9598 | Panagiotis Kanavos | ? CalculateBlockHashesRecursiveAsync(stream, blockSize, algorithm, hashes, index + 1) |
89 | 422c9598 | Panagiotis Kanavos | : Task.Factory.StartNew(() => hashes); |
90 | 422c9598 | Panagiotis Kanavos | if (read > 0) |
91 | 422c9598 | Panagiotis Kanavos | using (var hasher = HashAlgorithm.Create(algorithm)) |
92 | 422c9598 | Panagiotis Kanavos | { |
93 | 422c9598 | Panagiotis Kanavos | //This code was added for compatibility with the way Pithos calculates the last hash |
94 | 422c9598 | Panagiotis Kanavos | //We calculate the hash only up to the last non-null byte |
95 | 422c9598 | Panagiotis Kanavos | var lastByteIndex = Array.FindLastIndex(buffer, read - 1, aByte => aByte != 0); |
96 | 422c9598 | Panagiotis Kanavos | |
97 | 422c9598 | Panagiotis Kanavos | var hash = hasher.ComputeHash(buffer, 0, lastByteIndex + 1); |
98 | 422c9598 | Panagiotis Kanavos | hashes[index] = hash; |
99 | 422c9598 | Panagiotis Kanavos | } |
100 | 422c9598 | Panagiotis Kanavos | return nextTask; |
101 | 422c9598 | Panagiotis Kanavos | }).Unwrap(); |
102 | 422c9598 | Panagiotis Kanavos | } |
103 | 422c9598 | Panagiotis Kanavos | public static async Task<ConcurrentDictionary<int, byte[]>> CalculateBlockHashesAsync(FileStream stream, int blockSize, string algorithm, ConcurrentDictionary<int, byte[]> hashes = null, int index = 0) |
104 | 422c9598 | Panagiotis Kanavos | { |
105 | 422c9598 | Panagiotis Kanavos | if (stream == null) |
106 | 422c9598 | Panagiotis Kanavos | throw new ArgumentNullException("stream"); |
107 | 422c9598 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(algorithm)) |
108 | 422c9598 | Panagiotis Kanavos | throw new ArgumentNullException("algorithm"); |
109 | 422c9598 | Panagiotis Kanavos | if (blockSize <= 0) |
110 | 422c9598 | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero "); |
111 | 422c9598 | Panagiotis Kanavos | Contract.EndContractBlock(); |
112 | 422c9598 | Panagiotis Kanavos | |
113 | 422c9598 | Panagiotis Kanavos | |
114 | 422c9598 | Panagiotis Kanavos | if (hashes == null) |
115 | 422c9598 | Panagiotis Kanavos | hashes = new ConcurrentDictionary<int, byte[]>(); |
116 | 422c9598 | Panagiotis Kanavos | |
117 | 422c9598 | Panagiotis Kanavos | var buffer = new byte[blockSize]; |
118 | 422c9598 | Panagiotis Kanavos | int read; |
119 | 422c9598 | Panagiotis Kanavos | while ((read = await stream.ReadAsync(buffer, 0, blockSize)) > 0) |
120 | 422c9598 | Panagiotis Kanavos | { |
121 | 422c9598 | Panagiotis Kanavos | //TODO: identify the value of index |
122 | 422c9598 | Panagiotis Kanavos | |
123 | 422c9598 | Panagiotis Kanavos | using (var hasher = HashAlgorithm.Create(algorithm)) |
124 | 422c9598 | Panagiotis Kanavos | { |
125 | 422c9598 | Panagiotis Kanavos | //This code was added for compatibility with the way Pithos calculates the last hash |
126 | 422c9598 | Panagiotis Kanavos | //We calculate the hash only up to the last non-null byte |
127 | 422c9598 | Panagiotis Kanavos | var lastByteIndex = Array.FindLastIndex(buffer, read - 1, aByte => aByte != 0); |
128 | 422c9598 | Panagiotis Kanavos | |
129 | 422c9598 | Panagiotis Kanavos | var hash = hasher.ComputeHash(buffer, 0, lastByteIndex + 1); |
130 | 422c9598 | Panagiotis Kanavos | hashes[index] = hash; |
131 | 422c9598 | Panagiotis Kanavos | } |
132 | 422c9598 | Panagiotis Kanavos | index += read; |
133 | 422c9598 | Panagiotis Kanavos | }; |
134 | 422c9598 | Panagiotis Kanavos | return hashes; |
135 | 422c9598 | Panagiotis Kanavos | } |
136 | 422c9598 | Panagiotis Kanavos | |
137 | 422c9598 | Panagiotis Kanavos | public static async Task<ConcurrentDictionary<int, byte[]>> CalculateBlockHashesAgentAsync(FileStream stream, int blockSize, string algorithm, int parallelism) |
138 | 422c9598 | Panagiotis Kanavos | { |
139 | 422c9598 | Panagiotis Kanavos | if (stream == null) |
140 | 422c9598 | Panagiotis Kanavos | throw new ArgumentNullException("stream"); |
141 | 422c9598 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(algorithm)) |
142 | 422c9598 | Panagiotis Kanavos | throw new ArgumentNullException("algorithm"); |
143 | 422c9598 | Panagiotis Kanavos | if (blockSize <= 0) |
144 | 422c9598 | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero "); |
145 | 422c9598 | Panagiotis Kanavos | Contract.EndContractBlock(); |
146 | 422c9598 | Panagiotis Kanavos | |
147 | 422c9598 | Panagiotis Kanavos | var hashes = new ConcurrentDictionary<int, byte[]>(); |
148 | 422c9598 | Panagiotis Kanavos | |
149 | 6bcdd8e2 | Panagiotis Kanavos | var path = stream.Name; |
150 | 6bcdd8e2 | Panagiotis Kanavos | var size = stream.Length; |
151 | 6bcdd8e2 | Panagiotis Kanavos | Log.DebugFormat("Hashing [{0}] size [{1}]",path,size); |
152 | 6bcdd8e2 | Panagiotis Kanavos | |
153 | 6bcdd8e2 | Panagiotis Kanavos | /* |
154 | 422c9598 | Panagiotis Kanavos | var options = new ExecutionDataflowBlockOptions {BoundedCapacity = parallelism,MaxDegreeOfParallelism=parallelism}; |
155 | 422c9598 | Panagiotis Kanavos | var hashBlock=new ActionBlock<Tuple<int,byte[]>>(input=> |
156 | 422c9598 | Panagiotis Kanavos | { |
157 | 422c9598 | Panagiotis Kanavos | int idx = input.Item1; |
158 | 422c9598 | Panagiotis Kanavos | byte[] block = input.Item2; |
159 | 422c9598 | Panagiotis Kanavos | using (var hasher = HashAlgorithm.Create(algorithm)) |
160 | 422c9598 | Panagiotis Kanavos | { |
161 | 422c9598 | Panagiotis Kanavos | //This code was added for compatibility with the way Pithos calculates the last hash |
162 | 422c9598 | Panagiotis Kanavos | //We calculate the hash only up to the last non-null byte |
163 | 422c9598 | Panagiotis Kanavos | var lastByteIndex = Array.FindLastIndex(block, block.Length-1, aByte => aByte != 0); |
164 | 422c9598 | Panagiotis Kanavos | |
165 | 422c9598 | Panagiotis Kanavos | var hash = hasher.ComputeHash(block, 0, lastByteIndex + 1); |
166 | 422c9598 | Panagiotis Kanavos | hashes[idx] = hash; |
167 | 422c9598 | Panagiotis Kanavos | } |
168 | 422c9598 | Panagiotis Kanavos | },options); |
169 | 6bcdd8e2 | Panagiotis Kanavos | */ |
170 | 422c9598 | Panagiotis Kanavos | |
171 | 422c9598 | Panagiotis Kanavos | var buffer = new byte[blockSize]; |
172 | 422c9598 | Panagiotis Kanavos | int read; |
173 | 422c9598 | Panagiotis Kanavos | int index = 0; |
174 | 6bcdd8e2 | Panagiotis Kanavos | using (var hasher = HashAlgorithm.Create(algorithm)) |
175 | 422c9598 | Panagiotis Kanavos | { |
176 | 6bcdd8e2 | Panagiotis Kanavos | while ((read = await stream.ReadAsync(buffer, 0, blockSize)) > 0) |
177 | 6bcdd8e2 | Panagiotis Kanavos | { |
178 | 6bcdd8e2 | Panagiotis Kanavos | // var block = new byte[read]; |
179 | 6bcdd8e2 | Panagiotis Kanavos | |
180 | 6bcdd8e2 | Panagiotis Kanavos | //This code was added for compatibility with the way Pithos calculates the last hash |
181 | 6bcdd8e2 | Panagiotis Kanavos | //We calculate the hash only up to the last non-null byte |
182 | 6bcdd8e2 | Panagiotis Kanavos | var lastByteIndex = Array.FindLastIndex(buffer, read - 1, aByte => aByte != 0); |
183 | 6bcdd8e2 | Panagiotis Kanavos | |
184 | 6bcdd8e2 | Panagiotis Kanavos | var hash = hasher.ComputeHash(buffer, 0, lastByteIndex + 1); |
185 | 6bcdd8e2 | Panagiotis Kanavos | Log.DebugFormat("Hashed [{0}] [{1}/{2}] [{3:p}]", path, index,size,(double)index/size); |
186 | 6bcdd8e2 | Panagiotis Kanavos | hashes[index] = hash; |
187 | 6bcdd8e2 | Panagiotis Kanavos | index += read; |
188 | 6bcdd8e2 | Panagiotis Kanavos | } |
189 | 6bcdd8e2 | Panagiotis Kanavos | |
190 | 6bcdd8e2 | Panagiotis Kanavos | /* |
191 | 6bcdd8e2 | Panagiotis Kanavos | Buffer.BlockCopy(buffer,0,block,0,read); |
192 | 6bcdd8e2 | Panagiotis Kanavos | await hashBlock.SendAsync(Tuple.Create(index, block)); |
193 | 6bcdd8e2 | Panagiotis Kanavos | */ |
194 | 6bcdd8e2 | Panagiotis Kanavos | |
195 | 6bcdd8e2 | Panagiotis Kanavos | } |
196 | 6bcdd8e2 | Panagiotis Kanavos | |
197 | 422c9598 | Panagiotis Kanavos | |
198 | 6bcdd8e2 | Panagiotis Kanavos | /* |
199 | 422c9598 | Panagiotis Kanavos | hashBlock.Complete(); |
200 | 422c9598 | Panagiotis Kanavos | await hashBlock.Completion; |
201 | 6bcdd8e2 | Panagiotis Kanavos | */ |
202 | 422c9598 | Panagiotis Kanavos | |
203 | 422c9598 | Panagiotis Kanavos | return hashes; |
204 | 422c9598 | Panagiotis Kanavos | } |
205 | 422c9598 | Panagiotis Kanavos | |
206 | 422c9598 | Panagiotis Kanavos | static BlockHashAlgorithms() |
207 | 422c9598 | Panagiotis Kanavos | { |
208 | 422c9598 | Panagiotis Kanavos | CalculateBlockHash = CalculateBlockHashesRecursiveAsync; |
209 | 422c9598 | Panagiotis Kanavos | } |
210 | 422c9598 | Panagiotis Kanavos | } |
211 | 422c9598 | Panagiotis Kanavos | } |