using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Duplicati.Library.Main.ForestHash.Database { /// /// Provides a simple hash-table like lookup, /// similar to a MRU cache /// internal class HashLookupWithData { private const long MAX_MEMORY = 32 * 1024 * 1024; //32mb /// /// The lookup table with all values /// private KeyValuePair[] m_lookup; /// /// Typecasted size of table /// private ulong m_modulo; public HashLookupWithData(uint elementsize, ulong memorylimit = MAX_MEMORY) { //Allocate as a large boolean/bit array m_lookup = new KeyValuePair[Math.Max(32, Math.Max(1024, memorylimit * 8) / elementsize)]; m_modulo = (ulong)m_lookup.Length; } /// /// Adds a hash to the table /// /// The hash key /// The actual hash data public void AddHash(ulong key, TKey value, TValue data) { //Textbox hashing, the value modulo number of entries // works because the input is high quality random data var bit = key % m_modulo; m_lookup[bit] = new KeyValuePair(value, data); } /// /// Queries the table to see if a hash exists. /// A true result value is definitive, a false result value should be interpreted as maybe. /// /// The hash key /// The actual hash data /// True if the hash was found, false otherwise public bool HashExists(ulong key, TKey value, out TValue data) { //Textbox hashing, the value modulo number of entries // works because the input is high quality random data var bit = key % m_modulo; var el = m_lookup[bit]; if (object.Equals(el.Key, value)) { data = el.Value; return true; } else { data = default(TValue); return false; } } /// /// Calculates number of used entries in the table /// public ulong Entries { get { ulong c = 0; foreach (var x in m_lookup) if (!object.Equals(x.Key, default(TKey))) c++; return c; } } /// /// Gets a value between 0 and 1 descring how /// many entries are used /// public double TableUsageRatio { get { return Entries / (double)m_lookup.Length; } } } }