Exemplo n.º 1
0
        /// <summary>
        /// Decode the filter.
        /// </summary>
        /// <typeparam name="TEntity">The type of the entity</typeparam>
        /// <typeparam name="TId">The type of the entity identifier</typeparam>
        /// <typeparam name="TCount">The type of the occurence count for the invertible Bloom filter.</typeparam>
        /// <param name="filter">The Bloom filter data to decode</param>
        /// <param name="configuration">The Bloom filter configuration</param>
        /// <param name="listA">Items in the original set, but not in the subtracted set.</param>
        /// <param name="listB">Items not in the original set, but in the subtracted set.</param>
        /// <param name="modifiedEntities">items in both sets, but with a different value.</param>
        /// <param name="pureList">Optional list of pure items</param>
        /// <returns><c>true</c> when the decode was successful, else <c>false</c>.</returns>
        private static bool?Decode <TEntity, TId, TCount>(
            this IInvertibleBloomFilterData <TId, int, TCount> filter,
            IInvertibleBloomFilterConfiguration <TEntity, TId, int, TCount> configuration,
            HashSet <TId> listA,
            HashSet <TId> listB,
            HashSet <TId> modifiedEntities = null,
            Stack <long> pureList          = null)
            where TId : struct
            where TCount : struct
        {
            if (filter == null)
            {
                return(null);
            }
            var countComparer = Comparer <TCount> .Default;

            if (pureList == null)
            {
                pureList = new Stack <long>(LongEnumerable.Range(0L, filter.BlockSize)
                                            .Where(i => configuration.IsPure(filter, i))
                                            .Select(i => i));
            }
            var countsIdentity = configuration.CountConfiguration.Identity;

            while (pureList.Any())
            {
                var pureIdx = pureList.Pop();
                if (!configuration.IsPure(filter, pureIdx))
                {
                    continue;
                }
                var id         = filter.IdSumProvider[pureIdx];
                var hashSum    = filter.HashSumProvider[pureIdx];
                var count      = filter.Counts[pureIdx];
                var negCount   = countComparer.Compare(count, countsIdentity) < 0;
                var isModified = false;
                foreach (var position in configuration.Probe(filter, hashSum))
                {
                    var wasZero = configuration.CountConfiguration.Comparer.Compare(filter.Counts[position], countsIdentity) == 0;
                    if (configuration.IsPure(filter, position) &&
                        !configuration.HashEqualityComparer.Equals(filter.HashSumProvider[position], hashSum) &&
                        configuration.IdEqualityComparer.Equals(id, filter.IdSumProvider[position]))
                    {
                        modifiedEntities?.Add(id);
                        isModified = true;
                        if (negCount)
                        {
                            filter.Add(configuration, id, filter.HashSumProvider[position], position);
                        }
                        else
                        {
                            filter.Remove(configuration, id, filter.HashSumProvider[position], position);
                        }
                    }
                    else
                    {
                        if (negCount)
                        {
                            filter.Add(configuration, id, hashSum, position);
                        }
                        else
                        {
                            filter.Remove(configuration, id, hashSum, position);
                        }
                    }
                    if (!wasZero && configuration.IsPure(filter, position))
                    {
                        //count became pure, add to the list.
                        pureList.Push(position);
                    }
                }
                if (isModified)
                {
                    continue;
                }
                if (negCount)
                {
                    listB.Add(id);
                }
                else
                {
                    listA.Add(id);
                }
            }
            modifiedEntities?.MoveModified(listA, listB);
            return(filter.IsCompleteDecode(configuration));
        }