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 Newtonsoft.Json;
+
using System.Linq;
+using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Pithos.Network
private const int DEFAULT_BLOCK_SIZE = 4*1024*1024;
public string BlockHash { get; set; }
public int BlockSize { get; set; }
- public long Bytes { 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; }
{
get { return _topHash.Value; }
}
- private readonly Lazy<string> _topHash2;
- public string TopHash2
- {
- get { return _topHash2.Value; }
- }
- private IEnumerable<byte[]> _hashes;
- public IEnumerable<byte[]> Hashes
+ private IList<byte[]> _hashes;
+
+ public IList<byte[]> Hashes
{
get { return _hashes; }
set
}
}
- public TreeHash(string algorithm)
+ [ContractInvariantMethod]
+ private void Invariants()
+ {
+ Contract.Invariant(_bytes>=0);
+ }
+
+
+ public TreeHash(string algorithm)
{
BlockHash = algorithm;
_topHash = new Lazy<byte[]>(() =>
string[] hashes=null ;
if (Hashes!=null)
- hashes= Hashes.Select(hash=>hash.ToHashString()).ToArray();
+ hashes= GetHashesAsStrings();
value["hashes"]= new JArray(hashes);
value["block_size"] = BlockSize;
value["bytes"] = Bytes;
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, int> _blocks;
+ //Retruns the hashes as a dictionary to the block location. Used to locate blocks
+ public IDictionary<string,int> HashDictionary
+ {
+ get
+ {
+ Func<ConcurrentDictionary<string, int>> blocksInit = () =>
+ {
+ var blocks =
+ new ConcurrentDictionary<string, int>();
+ if (Hashes == null)
+ return blocks;
+
+ var blockIndex = 0;
+ foreach (var hash in this.Hashes)
+ {
+ blocks[hash.ToHashString()] = blockIndex++;
+ }
+ return blocks;
+ };
+
+ return _blocks ?? (_blocks = blocksInit());
+ }
+ }
+
//Saves the Json representation to a file
public Task Save(string filePath)
{
+ if (String.IsNullOrWhiteSpace(filePath))
+ throw new ArgumentNullException("filePath");
+ Contract.EndContractBlock();
+
var fileName = FileId.ToString("N");
var path = Path.Combine(filePath, fileName);
if (!Directory.Exists(filePath))
public static TreeHash Parse(string json)
{
if (String.IsNullOrWhiteSpace(json))
- return Empty;
+ 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 treeHash = new TreeHash(blockHash)
{
BlockSize = size,
- Hashes = hashValues,
+ Hashes = hashValues.ToList(),
Bytes = bytes
};
return treeHash;