*/
void handleGossip(Gossip gossip) {
long my_low=0, my_high=0, their_low, their_high;
Hashtable ht=null;
Digest their_digest;
NakReceiverWindow win;
Message msg;
Address dest;
Vector new_dests;
PbcastHeader hdr;
List missing_msgs; // list of missing messages (for retransmission) (List of Longs)
if(trace)
log.trace("(from " + local_addr + ") received gossip " + gossip.shortForm() + " from " + gossip.sender);
if(gossip == null || gossip.digest == null) {
if(warn) log.warn("gossip is null or digest is null");
return;
}
/* 1. If gossip sender is null, we cannot ask it for missing messages anyway, so discard gossip ! */
if(gossip.sender == null) {
if(log.isErrorEnabled()) log.error("sender of gossip is null; " +
"don't know where to send XMIT_REQ to. Discarding gossip");
return;
}
/* 2. Don't process the gossip if the sender of the gossip is not a member anymore. If it is a newly
joined member, discard it as well (we can't tell the difference). When the new member will be
added to the membership, then its gossips will be processed */
if(!members.contains(gossip.sender)) {
if(warn) log.warn("sender " + gossip.sender +
" is not a member. Gossip will not be processed");
if(shun)
shunInvalidGossiper(gossip.sender);
return;
}
/* 3. If this gossip was received before, just discard it and return (don't process the
same gossip twice). This prevents flooding of the gossip sender with retransmission reqs */
while(gossip_list.size() >= max_gossip_cache) // first delete oldest gossips
gossip_list.removeFromHead();
if(gossip_list.contains(gossip)) // already received, don't re-broadcast
return;
else
gossip_list.add(gossip.copy()); // add to list of received gossips
/* 4. Send a HEARD_FROM event containing all members in the gossip-chain down to the FD layer.
This ensures that we don't suspect them */
seen_list=gossip.getSeenList();
if(seen_list.size() > 0)
passDown(new Event(Event.HEARD_FROM, seen_list.clone()));
/* 5. Compare their digest against ours. Find out if some messages in the their digest are
not in our digest. If yes, put them in the 'ht' hashtable for retransmission */
their_digest=gossip.digest;
Map.Entry entry;
Address sender;
org.jgroups.protocols.pbcast.Digest.Entry val;
for(Iterator it=their_digest.senders.entrySet().iterator(); it.hasNext();) {
entry=(Map.Entry)it.next();
sender=(Address)entry.getKey();
val=(org.jgroups.protocols.pbcast.Digest.Entry)entry.getValue();
their_low=val.low_seqno;
their_high=val.high_seqno;
if(their_low == 0 && their_high == 0)
continue; // won't have any messages for this sender, don't even re-send
win=(NakReceiverWindow) digest.get(sender);
if(win == null) {
// this specific sender in this digest is probably not a member anymore, new digests
// won't contain it. for now, just ignore it. if it is a new member, it will be in the next
// gossips
if(warn) log.warn("sender " + sender + " not found, skipping...");
continue;
}
my_low=win.getLowestSeen();
my_high=win.getHighestSeen();
if(my_high < their_high) {
// changed by Bela (June 26 2003) - replaced my_high with my_low (not tested though !)
if(my_low + 1 < their_low) {
}
else {
missing_msgs=win.getMissingMessages(my_high, their_high);
if(missing_msgs != null) {
if(log.isInfoEnabled())
log.info("asking " + gossip.sender + " for retransmission of " +
sender + ", missing messages: " + missing_msgs + "\nwin for " + sender + ":\n" + win + '\n');
if(ht == null) ht=new Hashtable();