/// <summary>
        ///   Insert hash into the RAM Storage. Be careful, there should be a Track object already inserted into the Storage.
        /// </summary>
        /// <param name = "hash">Hash signature that corresponds to a specific track</param>
        public void InsertHash(HashSignature hash)
        {
            fingerprints[hash.Track].Add(hash);
            long[] signature = hash.Signature;

            /*Lock insertion in the hash-tables as it keys are verified*/
            lock (hashTables.SyncRoot)
            {
                for (int i = 0; i < numberOfHashTables; i++)
                {
                    if (!hashTables[i].ContainsKey(signature[i]))
                    {
                        hashTables[i][signature[i]] = new HashSet<Track>();
                    }

                    hashTables[i][signature[i]].Add(hash.Track);
                }
            }
        }
        private IEnumerable<HashSignature> GetSignatures(IEnumerable<bool[]> fingerprints, Track track, int hashTables, int hashKeys)
        {
            List<HashSignature> signatures = new List<HashSignature>();
            foreach (bool[] fingerprint in fingerprints)
            {
                long[] buckets = combinedHashingAlgorithm.Hash(fingerprint, hashTables, hashKeys).Item2;
                long[] hashSignature = new long[buckets.Length];
                int tableCount = 0;
                foreach (long bucket in buckets)
                {
                    hashSignature[tableCount++] = bucket;
                }

                HashSignature hash = new HashSignature(track, hashSignature); /*associate track to hash-signature*/
                signatures.Add(hash);
            }

            return signatures; /*Return the signatures*/
        }
        /// <summary>
        ///   Get tracks that correspond to a specific hash signature and pass the threshold value
        /// </summary>
        /// <param name = "hashSignature">Hash signature of the track</param>
        /// <param name = "hashTableThreshold">Number of threshold tables</param>
        /// <returns>Possible candidates</returns>
        public Dictionary<Track, int> GetTracks(HashSignature hashSignature, int hashTableThreshold)
        {
            Dictionary<Track, int> result = new Dictionary<Track, int>();
            long[] signature = hashSignature.Signature;

            // loop through all 25 hash tables
            for (int i = 0; i < numberOfHashTables; i++)
            {
                if (hashTables[i].ContainsKey(signature[i]))
                {
                    HashSet<Track> tracks = hashTables[i][signature[i]]; // get the set of tracks that map to a specific hash signature

                    // select all tracks except the original one
                    foreach (Track track in tracks.Where(t => t.Id != hashSignature.Track.Id))
                    {
                        if (!result.ContainsKey(track))
                        {
                            result[track] = 1;
                        }
                        else
                        {
                            result[track]++;
                        }
                    }
                }
            }

            // select only those tracks that passed threshold votes
            Dictionary<Track, int> filteredResult = result.Where(item => item.Value >= hashTableThreshold).ToDictionary(item => item.Key, item => item.Value);
            return filteredResult;
        }