/// <summary> /// Given a serialized estimator (<paramref name="estimatorStream"/>), determine the size of the difference, create a Bloom filter for the difference and return that Bloom filter /// </summary> /// <param name="estimatorStream">The estimator</param> /// <param name="otherActor">The other party involved</param> /// <returns></returns> public MemoryStream RequestFilter(MemoryStream estimatorStream, Actor <TCount> otherActor) { Console.WriteLine($"Estimator size: {estimatorStream.Length} "); var otherEstimator = (IHybridEstimatorData <int, TCount>) _protobufModel.Deserialize(estimatorStream, null, typeof(HybridEstimatorData <int, TCount>)); var estimator = _hybridEstimatorFactory.CreateMatchingEstimator(otherEstimator, _configuration, _dataSet.LongCount()); foreach (var item in _dataSet) { estimator.Add(item); } var estimate = estimator.Decode(otherEstimator); if (estimate == null) { //additional communication step needed to create a new estimator. byte failedDecodeCount = 0; while (estimate == null && failedDecodeCount < 5) { estimator = _hybridEstimatorFactory.Create(_configuration, _dataSet.Count(), ++failedDecodeCount); foreach (var item in _dataSet) { estimator.Add(item); } using (var stream = new MemoryStream()) { _protobufModel.Serialize(stream, estimator.Extract()); stream.Position = 0; estimate = otherActor.GetEstimate(stream); } } if (estimate == null) { throw new NullReferenceException("Did not negotiate a good estimate"); } } var filter = _bloomFilterFactory.Create(_configuration, estimate.Value, 0.001F, true); foreach (var item in _dataSet) { filter.Add(item); } var result = new MemoryStream(); _protobufModel.Serialize(result, filter.Extract()); result.Position = 0; Console.WriteLine($"Filter size: {result.Length} "); return(result); }
/// <summary> /// Constructor /// </summary> /// <param name="dataSet">The data set for this actor</param> /// <param name="hybridEstimatorFactory">Factory for creating estimators</param> /// <param name="bloomFilterFactory">Factory for creating Bloom filters</param> /// <param name="configuration">Bloom filter configuration to use</param> public PrecalculatedActor(IList <TestEntity> dataSet, IHybridEstimatorFactory hybridEstimatorFactory, IInvertibleBloomFilterFactory bloomFilterFactory, IInvertibleBloomFilterConfiguration <TestEntity, long, int, TCount> configuration) { _protobufModel = TypeModel.Create(); _protobufModel.UseImplicitZeroDefaults = true; _hybridEstimatorFactory = hybridEstimatorFactory; _configuration = configuration; //terribly over size the estimator. _estimator = _hybridEstimatorFactory.Create(_configuration, 100000); foreach (var itm in dataSet) { _estimator.Add(itm); } //sized to number of differences it can handle, not to the size of the data. _filter = bloomFilterFactory.Create(_configuration, 5000, 0.001F, true); foreach (var item in dataSet) { _filter.Add(item); } }