/// <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"></param> /// <returns></returns> public MemoryStream RequestFilter(MemoryStream estimatorStream, PrecalculatedActor <TCount> otherActor) { Console.WriteLine($"Estimator size: {estimatorStream.Length} "); var otherEstimator = (IHybridEstimatorData <int, TCount>) _protobufModel.Deserialize(estimatorStream, null, typeof(HybridEstimatorData <int, TCount>)); 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) { var estimator = _hybridEstimatorFactory.Extract(_configuration, _estimator, failedDecodeCount); using (var stream = new MemoryStream()) { _protobufModel.Serialize(stream, estimator); stream.Position = 0; estimate = otherActor.GetEstimate(stream); } failedDecodeCount++; } if (estimate == null) { throw new NullReferenceException("Did not negotiate a good estimate"); } } var result = new MemoryStream(); _protobufModel.Serialize(result, _configuration.DataFactory.Extract(_configuration, _filter, estimate.Value)); result.Position = 0; Console.WriteLine($"Filter size: {result.Length} "); return(result); }
/// <summary> /// Given the actor, determine the difference. /// </summary> /// <param name="actor"></param> /// <returns></returns> public Tuple <HashSet <long>, HashSet <long>, HashSet <long> > GetDifference(PrecalculatedActor <TCount> actor) { using (var estimatorStream = new MemoryStream()) { var data = _hybridEstimatorFactory.Extract(_configuration, _estimator); _protobufModel.Serialize(estimatorStream, data); estimatorStream.Position = 0; //send the estimator to the other actor and receive the filter from that actor. var otherFilterStream = actor.RequestFilter(estimatorStream, this); var otherFilter = (IInvertibleBloomFilterData <long, int, TCount>) _protobufModel.Deserialize(otherFilterStream, null, _configuration.DataFactory.GetDataType <long, int, TCount>()); otherFilterStream.Dispose(); var onlyInThisSet = new HashSet <long>(); var onlyInOtherSet = new HashSet <long>(); var modified = new HashSet <long>(); var succes = _filter.SubtractAndDecode(onlyInThisSet, onlyInOtherSet, modified, otherFilter); //note: even when not successfully decoded for sure, the sets will contain info. return(new Tuple <HashSet <long>, HashSet <long>, HashSet <long> >(onlyInThisSet, onlyInOtherSet, modified)); } }