Revision 0c02aa65 trunk/Pithos.Core/Signature.cs
b/trunk/Pithos.Core/Signature.cs | ||
---|---|---|
1 |
using System; |
|
2 |
using System.Collections; |
|
3 |
using System.Collections.Concurrent; |
|
4 |
using System.Collections.Generic; |
|
1 | 5 |
using System.IO; |
2 | 6 |
using System.Security.Cryptography; |
3 | 7 |
using System.Text; |
8 |
using System.Threading.Tasks; |
|
9 |
using System.Linq; |
|
10 |
using Pithos.Core; |
|
4 | 11 |
|
5 | 12 |
public static class Signature |
6 | 13 |
{ |
... | ... | |
18 | 25 |
} |
19 | 26 |
return hash; |
20 | 27 |
} |
28 |
|
|
29 |
/*public static FileHashMap CalculateHashMap(string path, int blockSize) |
|
30 |
{ |
|
31 |
CalculateBlockHashes(path, blockSize) |
|
32 |
.ContinueWith(blockTask => |
|
33 |
{ |
|
34 |
var hashes = blockTask.Result; |
|
35 |
var hashMapHash = CalculateHashmapHash(hashes); |
|
36 |
return new FileHashMap {Hash = hashMapHash, Hashes = hashes}; |
|
37 |
}); |
|
38 |
}*/ |
|
39 |
|
|
40 |
public static Task<IList<FileHash>> CalculateBlockHashesAsync(string path, int blockSize) |
|
41 |
{ |
|
42 |
var hashMap = new ConcurrentQueue<FileHash>(); |
|
43 |
var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true); |
|
44 |
|
|
45 |
return stream.ReadBuffersAsync(blockSize, (buffer, read) => |
|
46 |
{ |
|
47 |
using (var hasher = SHA256.Create()) |
|
48 |
{ |
|
49 |
var hash = hasher.ComputeHash(buffer, 0, read); |
|
50 |
hashMap.Enqueue(new FileHash{FilePath=path,Value=hash}); |
|
51 |
} |
|
52 |
}).ContinueWith(t=> |
|
53 |
{ |
|
54 |
stream.Close(); |
|
55 |
return (IList<FileHash>)hashMap.ToList(); |
|
56 |
}); |
|
57 |
} |
|
58 |
//I'd rather return an enumerable of hash calculation tasks, each of which can |
|
59 |
//be use to further store the hashes to storage without first creating the list of hashes |
|
60 |
|
|
61 |
/* //Or I could pass an action object, just like ReadBuffers does |
|
62 |
Task.Factory.Iterate(HashMapIterator(stream, blockSize,hashMap.Enqueue)) |
|
63 |
.ContinueWith(t=> |
|
64 |
{ |
|
65 |
SHA256.Create(); |
|
66 |
});*/ |
|
67 |
|
|
68 |
|
|
69 |
|
|
70 |
public static byte[] CalculateHashmapHash(IList<FileHash> hashMap ) |
|
71 |
{ |
|
72 |
using (var stream = new MemoryStream()) |
|
73 |
using(var hasher=SHA256.Create()) |
|
74 |
{ |
|
75 |
foreach (var hash in hashMap) |
|
76 |
{ |
|
77 |
stream.Write(hash.Value, 0, hash.Value.Length); |
|
78 |
} |
|
79 |
return hasher.ComputeHash(stream); |
|
80 |
} |
|
81 |
} |
|
82 |
|
|
83 |
public static IEnumerable<byte[]> HashMapLinq(string path, int blockSize) |
|
84 |
{ |
|
85 |
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, true)) |
|
86 |
{ |
|
87 |
|
|
88 |
var query = from block in stream.GetIterator(blockSize).AsParallel().AsOrdered() |
|
89 |
select block; |
|
90 |
|
|
91 |
return query; |
|
92 |
} |
|
93 |
} |
|
94 |
|
|
95 |
public class Block |
|
96 |
{ |
|
97 |
public int Offset { get; set; } |
|
98 |
public byte[] Data { get; set; } |
|
99 |
} |
|
100 |
|
|
101 |
public static IEnumerable<byte[]> GetIterator(this Stream stream,int blockSize) |
|
102 |
{ |
|
103 |
var buffer = new byte[blockSize]; |
|
104 |
while(true) |
|
105 |
{ |
|
106 |
stream.Read(buffer, 0, buffer.Length); |
|
107 |
yield return buffer; |
|
108 |
} |
|
109 |
} |
|
110 |
|
|
111 |
|
|
112 |
|
|
113 |
private static IEnumerable<Task> HashMapIterator(Stream input, int bufferSize,Action<byte[]> hashAvailable ) |
|
114 |
{ |
|
115 |
// Create a buffer that will be used over and over |
|
116 |
var buffer = new byte[bufferSize]; |
|
117 |
|
|
118 |
using (var hasher = SHA256.Create()) |
|
119 |
{ |
|
120 |
// Until there's no more data |
|
121 |
while (true) |
|
122 |
{ |
|
123 |
// Asynchronously read a buffer and yield until the operation completes |
|
124 |
var readTask = input.ReadAsync(buffer, 0, buffer.Length); |
|
125 |
yield return readTask; |
|
126 |
|
|
127 |
// If there's no more data in the stream, we're done. |
|
128 |
if (readTask.Result <= 0) break; |
|
129 |
|
|
130 |
// Otherwise, hand the data off to the delegate |
|
131 |
var hashTask = Task.Factory.StartNew(() => hasher.ComputeHash(buffer, 0, readTask.Result)); |
|
132 |
yield return hashTask; |
|
133 |
hashAvailable(hashTask.Result); |
|
134 |
} |
|
135 |
} |
|
136 |
} |
|
137 |
|
|
21 | 138 |
} |
Also available in: Unified diff