-#region
-/* -----------------------------------------------------------------------
- * <copyright file="TreeHash.cs" company="GRNet">
- *
- * Copyright 2011-2012 GRNET S.A. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- *
- * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and
- * documentation are those of the authors and should not be
- * interpreted as representing official policies, either expressed
- * or implied, of GRNET S.A.
- * </copyright>
- * -----------------------------------------------------------------------
- */
-#endregion
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Text;
-using System.Threading.Tasks;
-
-using System.Linq;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-
-namespace Pithos.Network
-{
- public class TreeHash
- {
- private const string DEFAULT_HASH_ALGORITHM = "sha256";
- private const long DEFAULT_BLOCK_SIZE = 4*1024*1024;
- public string BlockHash { get; set; }
- public long BlockSize { get; set; }
-
- private long _bytes;
- public long Bytes
- {
- get
- {
- Contract.Ensures(Contract.Result<long>() >= 0);
- return _bytes;
- }
- set
- {
- if (value<0)
- throw new ArgumentOutOfRangeException("Bytes");
- Contract.Requires(value >= 0);
- Contract.EndContractBlock();
-
- _bytes = value;
- }
- }
-
-
-
- public Guid FileId { get; set; }
-
- private readonly Lazy<byte[]> _topHash;
- public byte[] TopHash
- {
- get { return _topHash.Value; }
- }
-
- private IList<byte[]> _hashes=new List<byte[]>();
-
- public IList<byte[]> Hashes
- {
- get { return _hashes; }
- set
- {
- _hashes = value;
- _topHash.Force();
- }
- }
-
- [ContractInvariantMethod]
- private void Invariants()
- {
- Contract.Invariant(_bytes>=0);
- }
-
-
- public TreeHash(string algorithm)
- {
- BlockHash = algorithm;
- _topHash = new Lazy<byte[]>(() =>
- {
- //
- //Cast the hashes to an IList or create a new list out of the hashes
- var hashMap = (_hashes as IList<byte[]>)??_hashes.ToList();
- return Signature.CalculateTopHash(hashMap, BlockHash);
- });
- }
-
- //Returns a Json representation of the hashes, as required by Pithos
- public string ToJson()
- {
- var value = new JObject();
- //We avoid using JObject's dynamic features because they use exceptions to detect new properties.
- value["block_hash"] = BlockHash;
- //Create a string array for all the hashes
-
- string[] hashes=null ;
- if (Hashes!=null)
- hashes= GetHashesAsStrings();
- value["hashes"]= new JArray(hashes);
- value["block_size"] = BlockSize;
- value["bytes"] = Bytes;
-
- var json = JsonConvert.SerializeObject(value, Formatting.None);
- return json;
- }
-
- private string[] _stringHashes;
- //Returns the hashes as an array of hash strings. Used for serialization to Json
- public string[] GetHashesAsStrings()
- {
- return _stringHashes
- ?? (_stringHashes = Hashes.Select(hash => hash.ToHashString()).ToArray());
- }
-
- ConcurrentDictionary<string, long> _blocks;
- //Retruns the hashes as a dictionary to the block location. Used to locate blocks
- public IDictionary<string,long> HashDictionary
- {
- get
- {
- Func<ConcurrentDictionary<string, long>> blocksInit = () =>
- {
- var blocks =
- new ConcurrentDictionary<string, long>();
- if (Hashes == null)
- return blocks;
-
- var blockIndex = 0;
- foreach (var hash in this.Hashes)
- {
- blocks[hash.ToHashString()] = blockIndex++;
- }
- return blocks;
- };
-
- return _blocks ?? (_blocks = blocksInit());
- }
- }
-
- public string MD5 { get; set; }
-
- //Saves the Json representation to a file
- public async Task Save(string filePath)
- {
- if (String.IsNullOrWhiteSpace(filePath))
- throw new ArgumentNullException("filePath");
-
- var fileName = FileId.ToString("N");
- var path = Path.Combine(filePath, fileName);
- if (!Directory.Exists(filePath))
- Directory.CreateDirectory(filePath);
-
- var json = await TaskEx.Run(() => ToJson()).ConfigureAwait(false);
- await FileAsync.WriteAllText(path, json).ConfigureAwait(false);
- }
-
- public static async Task<TreeHash> LoadTreeHash(string dataPath,Guid fileId)
- {
- var fileName = fileId.ToString("N");
- var path = Path.Combine(dataPath, fileName);
-
- var json = await FileAsync.ReadAllText(path).ConfigureAwait(false);
- var treeHash = Parse(json);
- treeHash.FileId = fileId;
- return treeHash;
- }
-
- public static TreeHash Empty = new TreeHash(DEFAULT_HASH_ALGORITHM)
- {
- BlockSize = DEFAULT_BLOCK_SIZE,
- Bytes = 0
- };
-
- //Parse a json string and return a TreeHash
- //Returns an empty TreeHash if the string is null or empty
- public static TreeHash Parse(string json)
- {
- if (String.IsNullOrWhiteSpace(json))
- return Empty;
-
- var value = JsonConvert.DeserializeObject<JObject>(json);
- if (value==null)
- throw new ArgumentException("The json parameter doesn't contain any json data","json");
- Contract.Assume(value!=null);
-
- var blockHash = (string) value["block_hash"];
- var size = value.Value<int>("block_size");
- var bytes = value.Value<long>("bytes");
- var hashes = value.Value<JArray>("hashes");
- var hashValues = from JToken token in hashes
- select token.Value<string>().ToBytes();
-
- var treeHash = new TreeHash(blockHash)
- {
- BlockSize = size,
- Hashes = hashValues.ToList(),
- Bytes = bytes
- };
- return treeHash;
- }
- }
+#region\r
+/* -----------------------------------------------------------------------\r
+ * <copyright file="TreeHash.cs" company="GRNet">\r
+ * \r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ * 1. Redistributions of source code must retain the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer.\r
+ *\r
+ * 2. Redistributions in binary form must reproduce the above\r
+ * copyright notice, this list of conditions and the following\r
+ * disclaimer in the documentation and/or other materials\r
+ * provided with the distribution.\r
+ *\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ * </copyright>\r
+ * -----------------------------------------------------------------------\r
+ */\r
+#endregion\r
+using System;\r
+using System.Collections.Concurrent;\r
+using System.Collections.Generic;\r
+using System.Diagnostics.Contracts;\r
+using System.IO;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+using System.Linq;\r
+using Newtonsoft.Json;\r
+using Newtonsoft.Json.Linq;\r
+\r
+namespace Pithos.Network\r
+{\r
+ public class TreeHash\r
+ {\r
+ public const string DEFAULT_HASH_ALGORITHM = "sha256";\r
+ public const long DEFAULT_BLOCK_SIZE = 4*1024*1024;\r
+ public string BlockHash { get; set; }\r
+ public long BlockSize { get; set; }\r
+ \r
+ private long _bytes;\r
+ public long Bytes\r
+ {\r
+ get\r
+ {\r
+ Contract.Ensures(Contract.Result<long>() >= 0);\r
+ return _bytes;\r
+ }\r
+ set\r
+ {\r
+ if (value<0)\r
+ throw new ArgumentOutOfRangeException("Bytes");\r
+ Contract.Requires(value >= 0);\r
+ Contract.EndContractBlock();\r
+ \r
+ _bytes = value;\r
+ }\r
+ }\r
+ \r
+\r
+\r
+ public Guid FileId { get; set; }\r
+\r
+ private readonly Lazy<byte[]> _topHash; \r
+ public byte[] TopHash\r
+ {\r
+ get { return _topHash.Value; }\r
+ }\r
+\r
+ private IList<byte[]> _hashes=new List<byte[]>();\r
+\r
+ public IList<byte[]> Hashes\r
+ {\r
+ get { return _hashes; }\r
+ set\r
+ {\r
+ _hashes = value;\r
+ _topHash.Force();\r
+ }\r
+ }\r
+\r
+ [ContractInvariantMethod]\r
+ private void Invariants()\r
+ {\r
+ Contract.Invariant(_bytes>=0);\r
+ }\r
+ \r
+\r
+ public TreeHash(string algorithm)\r
+ {\r
+ BlockHash = algorithm; \r
+ _topHash = new Lazy<byte[]>(() =>\r
+ {\r
+ //\r
+ //Cast the hashes to an IList or create a new list out of the hashes\r
+ var hashMap = (_hashes as IList<byte[]>)??_hashes.ToList();\r
+ return Signature.CalculateTopHash(hashMap, BlockHash);\r
+ });\r
+ }\r
+\r
+ //Returns a Json representation of the hashes, as required by Pithos\r
+ public string ToJson()\r
+ {\r
+ var value = new JObject();\r
+ //We avoid using JObject's dynamic features because they use exceptions to detect new properties.\r
+ value["block_hash"] = BlockHash;\r
+ //Create a string array for all the hashes \r
+ \r
+ string[] hashes=null ;\r
+ if (Hashes!=null)\r
+ hashes= GetHashesAsStrings();\r
+ value["hashes"]= new JArray(hashes);\r
+ value["block_size"] = BlockSize;\r
+ value["bytes"] = Bytes;\r
+ \r
+ var json = JsonConvert.SerializeObject(value, Formatting.None);\r
+ return json;\r
+ }\r
+\r
+ private string[] _stringHashes;\r
+ //Returns the hashes as an array of hash strings. Used for serialization to Json\r
+ public string[] GetHashesAsStrings()\r
+ {\r
+ return _stringHashes \r
+ ?? (_stringHashes = Hashes.Select(hash => hash.ToHashString()).ToArray());\r
+ }\r
+\r
+ ConcurrentDictionary<string, long> _blocks;\r
+ \r
+ //Retruns the hashes as a dictionary to the block location. Used to locate blocks\r
+ public IDictionary<string,long> HashDictionary\r
+ {\r
+ get\r
+ {\r
+ Func<ConcurrentDictionary<string, long>> blocksInit = () =>\r
+ {\r
+ var blocks =\r
+ new ConcurrentDictionary<string, long>();\r
+ if (Hashes == null)\r
+ return blocks;\r
+\r
+ var blockIndex = 0;\r
+ foreach (var hash in this.Hashes)\r
+ {\r
+ blocks[hash.ToHashString()] = blockIndex++;\r
+ }\r
+ return blocks;\r
+ };\r
+\r
+ return _blocks ?? (_blocks = blocksInit());\r
+ }\r
+ }\r
+\r
+ private string _md5=Signature.MD5_EMPTY;\r
+ public string MD5\r
+ {\r
+ get { return _md5; }\r
+ set { _md5 = value; }\r
+ }\r
+\r
+ //Saves the Json representation to a file\r
+ public async Task Save(string filePath)\r
+ {\r
+ if (String.IsNullOrWhiteSpace(filePath))\r
+ throw new ArgumentNullException("filePath");\r
+\r
+ var fileName = FileId.ToString("N");\r
+ var path = Path.Combine(filePath, fileName);\r
+ if (!Directory.Exists(filePath))\r
+ Directory.CreateDirectory(filePath);\r
+\r
+ var json = await TaskEx.Run(() => ToJson()).ConfigureAwait(false);\r
+ await FileAsync.WriteAllText(path, json).ConfigureAwait(false);\r
+ }\r
+\r
+ public static async Task<TreeHash> LoadTreeHash(string dataPath,Guid fileId)\r
+ {\r
+ var fileName = fileId.ToString("N");\r
+ var path = Path.Combine(dataPath, fileName);\r
+\r
+ var json = await FileAsync.ReadAllText(path).ConfigureAwait(false);\r
+ var treeHash = Parse(json);\r
+ treeHash.FileId = fileId;\r
+ return treeHash;\r
+ }\r
+\r
+ public static TreeHash Empty = new TreeHash(DEFAULT_HASH_ALGORITHM)\r
+ {\r
+ BlockSize = DEFAULT_BLOCK_SIZE,\r
+ Bytes = 0\r
+ };\r
+\r
+ //Parse a json string and return a TreeHash\r
+ //Returns an empty TreeHash if the string is null or empty\r
+ public static TreeHash Parse(string json)\r
+ {\r
+ if (String.IsNullOrWhiteSpace(json))\r
+ return Empty; \r
+\r
+ var value = JsonConvert.DeserializeObject<JObject>(json);\r
+ if (value==null)\r
+ throw new ArgumentException("The json parameter doesn't contain any json data","json");\r
+ Contract.Assume(value!=null);\r
+\r
+ var blockHash = (string) value["block_hash"];\r
+ var size = value.Value<int>("block_size");\r
+ var bytes = value.Value<long>("bytes");\r
+ var hashes = value.Value<JArray>("hashes");\r
+ var hashValues = from JToken token in hashes\r
+ select token.Value<string>().ToBytes();\r
+\r
+ var treeHash = new TreeHash(blockHash)\r
+ {\r
+ BlockSize = size,\r
+ Hashes = hashValues.ToList(),\r
+ Bytes = bytes\r
+ };\r
+ return treeHash;\r
+ }\r
+ }\r
}
\ No newline at end of file