Revision 6e25cc48 trunk/Pithos.Network/Signature.cs

b/trunk/Pithos.Network/Signature.cs
159 159
                return finalHash;
160 160
            }
161 161
        }*/
162
        
163
        public static byte[] CalculateTopHash(IEnumerable<byte[]> hashMap, string algorithm)
162

  
163
        public static byte[] CalculateTopHash(IList<byte[]> hashMap, string algorithm)
164 164
        {
165 165
            if (hashMap == null)
166 166
                throw new ArgumentNullException("hashMap");
167 167
            if (String.IsNullOrWhiteSpace(algorithm))
168 168
                throw new ArgumentNullException("algorithm");
169
            Contract.EndContractBlock();
169
            Contract.EndContractBlock();            
170 170

  
171
            var hashCount = hashMap.Count();
171
            var hashCount = hashMap.Count;
172
            //The tophash of an empty hashmap is an empty array
172 173
            if (hashCount == 0)
173
                return null;
174
                return new byte[0];
175
            //The tophash of a one-item hashmap is the hash itself
174 176
            if (hashCount == 1)
175
                return hashMap.First();
177
                return hashMap[0];
176 178

  
177
            var newHashes=new List<byte[]>();
179
            //Calculate the required number of leaf nodes
178 180
            var leafs =(int)Math.Pow(2, Math.Ceiling(Math.Log(hashCount,2)));
179
            for (int i = 0; i < leafs;i+=2 )
180
            {
181
                using (var hasher = HashAlgorithm.Create(algorithm))
181
            //The size of all nodes is the same and equal to the size of the input hashes
182
            var hashSize = hashMap[0].Length;
183

  
184
            //If the hashmap containes fewer nodes than the required leaf count, we need to fill
185
            //the rest with empty blocks
186
            byte[] empty=null;            
187
            if (hashCount < leafs)
188
                empty = new byte[hashSize];
189

  
190
            //New hashes will be stored in a dictionary keyed by their step to preserve order
191
            var newHashes=new ConcurrentDictionary<int, byte[]>();            
192
            
193
            Parallel.For(0, leafs/2,
194
                (step, state) =>
182 195
                {
183
                    var block1 = i >hashCount - 1 ? new byte[hashMap.First().Length] : hashMap.ElementAt(i);
184
                    var block2 = i>hashCount-2 ? new byte[block1.Length] : hashMap.ElementAt(i+1);
185
                    
196
                    using (var hasher = HashAlgorithm.Create(algorithm))
197
                    {
198
                        var i = step*2;
199
                        var block1 = i <= hashCount - 1 ? hashMap[i] : empty;
200
                        var block2 = i <= hashCount - 2 ? hashMap[i + 1] : empty;
201

  
202
                        hasher.TransformBlock(block1, 0, block1.Length, null, 0);
203
                        hasher.TransformFinalBlock(block2, 0, block2.Length);
204

  
205
                        var finalHash = hasher.Hash;
206
                        //Store the final value in its proper place
207
                        newHashes[step] = finalHash;
208
                    }
209
                });
210
/*
211
            Parallel.For(0, leafs/2,
212
                () => HashAlgorithm.Create(algorithm),
213
                (step, state, hasher) =>
214
                {
215
                                 
216
                    var i = step*2;
217
                    var block1 = i <= hashCount - 1 ? hashMap[i]: empty;
218
                    var block2 = i <= hashCount - 2 ? hashMap[i + 1] : empty;
219

  
186 220
                    hasher.TransformBlock(block1, 0, block1.Length, null, 0);
187
                    hasher.TransformFinalBlock(block2, 0, block2.Length);                        
221
                    hasher.TransformFinalBlock(block2, 0, block2.Length);
222
                    
188 223
                    var finalHash = hasher.Hash;
189
                    newHashes.Add(finalHash);
190
                }                    
191
            }
192
            return CalculateTopHash(newHashes, algorithm);                   
224
                    //Store the final value in its proper place
225
                    newHashes[step] = finalHash;
226
                                        
227
                    return hasher;
228
                },
229
                hasher => hasher.Dispose());
230
*/
231
            //Extract the hashes to a list ordered by their step 
232
            var hashes = newHashes.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToList();
233
            return CalculateTopHash(hashes, algorithm);                   
193 234
        }
194 235

  
195 236
        
196 237

  
197
        public static string CalculateTopHash(string hashString, string algorithm)
238
      /*  public static string CalculateTopHash(string hashString, string algorithm)
198 239
        {
199 240
            if (String.IsNullOrWhiteSpace(algorithm))
200 241
                throw new ArgumentNullException("algorithm");
......
208 249
                var hash=hasher.ComputeHash(bytes);
209 250
                return hash.ToHashString();
210 251
            }
211
        }
252
        }*/
212 253

  
213 254
        private static Task<ConcurrentDictionary<int, byte[]>> CalculateBlockHashesAsync(FileStream stream, int blockSize, string algorithm, ConcurrentDictionary<int, byte[]> hashes, int index = 0)
214 255
        {

Also available in: Unified diff