use of io.atomix.primitive.protocol.map.MapDelegateEvent in project atomix by atomix.
the class AntiEntropyMapDelegate method antiEntropyCheckLocalItems.
/**
* Processes anti-entropy ad from peer by taking following actions: 1. If peer has an old entry, updates peer. 2. If
* peer indicates an entry is removed and has a more recent timestamp than the local entry, update local state.
*/
private List<MapDelegateEvent<K, V>> antiEntropyCheckLocalItems(AntiEntropyAdvertisement ad) {
final List<MapDelegateEvent<K, V>> externalEvents = Lists.newLinkedList();
final MemberId sender = ad.sender();
final List<MemberId> peers = ImmutableList.of(sender);
Set<String> staleOrMissing = new HashSet<>();
Set<String> locallyUnknown = new HashSet<>(ad.digest().keySet());
items.forEach((key, localValue) -> {
locallyUnknown.remove(key);
MapValue.Digest remoteValueDigest = ad.digest().get(key);
if (remoteValueDigest == null || localValue.isNewerThan(remoteValueDigest.timestamp())) {
// local value is more recent, push to sender
queueUpdate(new UpdateEntry(key, localValue), peers);
} else if (remoteValueDigest.isNewerThan(localValue.digest()) && remoteValueDigest.isTombstone()) {
// remote value is more recent and a tombstone: update local value
MapValue tombstone = MapValue.tombstone(remoteValueDigest.timestamp());
MapValue previousValue = removeInternal(key, Optional.empty(), Optional.of(tombstone));
if (previousValue != null && previousValue.isAlive()) {
externalEvents.add(new MapDelegateEvent<>(REMOVE, decodeKey(key), previousValue.get(this::decodeValue)));
}
} else if (remoteValueDigest.isNewerThan(localValue.digest())) {
// Not a tombstone and remote is newer
staleOrMissing.add(key);
}
});
// Keys missing in local map
staleOrMissing.addAll(locallyUnknown);
// Request updates that we missed out on
sendUpdateRequestToPeer(sender, staleOrMissing);
return externalEvents;
}
Aggregations