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 Proto.Msg.Status StatusToProto(Status status) { var proto = new Proto.Msg.Status { Chunk = (uint)status.Chunk, TotChunks = (uint)status.TotalChunks }; foreach (var entry in status.Digests) { proto.Entries.Add(new Proto.Msg.Status.Types.Entry { Key = entry.Key, Digest = ByteString.CopyFrom(entry.Value.ToByteArray()) }); } if (status.ToSystemUid.HasValue) { proto.HasToSystemUid = true; proto.ToSystemUid = status.ToSystemUid.Value; } if (status.FromSystemUid.HasValue) { proto.HasFromSystemUid = true; proto.FromSystemUid = status.FromSystemUid.Value; } return(proto); }
private void ReceiveStatus(IImmutableDictionary <string, ByteString> otherDigests, int chunk, int totChunks) { if (_log.IsDebugEnabled) { _log.Debug("Received gossip status from {0}, chunk {1} of {2} containing {3}", Sender.Path.Address, chunk, totChunks, string.Join(", ", otherDigests.Keys)); } var otherDifferentKeys = otherDigests .Where(x => IsOtherDifferent(x.Key, x.Value)) .Select(x => x.Key) .ToArray(); var otherKeys = otherDigests.Keys.ToImmutableHashSet(); var myKeys = (totChunks == 1 ? _dataEntries.Keys : _dataEntries.Keys.Where(x => 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}, containing {1}", Sender.Path.Address, string.Join(", ", keys)); } var g = new Gossip(keys.Select(k => new KeyValuePair <string, DataEnvelope>(k, GetData(k))).ToImmutableDictionary(), otherDifferentKeys.Any()); 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); } }