private void GossipTo(Address address) { var to = Replica(address); if (_dataEntries.Count <= _settings.MaxDeltaElements) { var status = new Internal.Status(_dataEntries.Select(x => new KeyValuePair <string, ByteString>(x.Key, GetDigest(x.Key))).ToImmutableDictionary(), 0, 1); to.Tell(status); } else { var totChunks = _dataEntries.Count / _settings.MaxDeltaElements; for (var i = 1; i <= Math.Min(totChunks, 10); i++) { if (totChunks == _statusTotChunks) { _statusCount++; } else { _statusCount = ThreadLocalRandom.Current.Next(0, totChunks); _statusTotChunks = totChunks; } var chunk = (int)(_statusCount % totChunks); var entries = _dataEntries.Where(x => Math.Abs(x.Key.GetHashCode()) % totChunks == chunk) .Select(x => new KeyValuePair <string, ByteString>(x.Key, GetDigest(x.Key))) .ToImmutableDictionary(); var status = new Internal.Status(entries, chunk, totChunks); to.Tell(status); } } }
private void ReceiveStatus(IImmutableDictionary <string, ByteString> otherDigests, int chunk, int totChunks) { if (_log.IsDebugEnabled) { _log.Debug("Received gossip status from [{0}], chunk {1}/{2} containing [{3}]", Sender.Path.Address, chunk + 1, totChunks, string.Join(", ", otherDigests.Keys)); } // if no data was send we do nothing if (otherDigests.Count == 0) { return; } var otherDifferentKeys = otherDigests .Where(x => IsOtherDifferent(x.Key, x.Value)) .Select(x => x.Key) .ToImmutableHashSet(); var otherKeys = otherDigests.Keys.ToImmutableHashSet(); var myKeys = (totChunks == 1 ? _dataEntries.Keys : _dataEntries.Keys.Where(x => Math.Abs(x.GetHashCode()) % totChunks == chunk)) .ToImmutableHashSet(); var otherMissingKeys = myKeys.Except(otherKeys); var keys = otherDifferentKeys .Union(otherMissingKeys) .Take(_settings.MaxDeltaElements) .ToArray(); if (keys.Length != 0) { if (_log.IsDebugEnabled) { _log.Debug("Sending gossip to [{0}]: {1}", Sender.Path.Address, string.Join(", ", keys)); } var g = new Gossip(keys.Select(k => new KeyValuePair <string, DataEnvelope>(k, GetData(k))).ToImmutableDictionary(), !otherDifferentKeys.IsEmpty); Sender.Tell(g); } var myMissingKeys = otherKeys.Except(myKeys); if (!myMissingKeys.IsEmpty) { if (Context.System.Log.IsDebugEnabled) { Context.System.Log.Debug("Sending gossip status to {0}, requesting missing {1}", Sender.Path.Address, string.Join(", ", myMissingKeys)); } var status = new Internal.Status(myMissingKeys.Select(x => new KeyValuePair <string, ByteString>(x, NotFoundDigest)).ToImmutableDictionary(), chunk, totChunks); Sender.Tell(status); } }