log.trace("removed " + sender + " from previous_members as we received a message from it");
previous_members.remove(sender);
}
Entry entry;
AckReceiverWindow win;
synchronized(connections) {
entry=connections.get(sender);
if(entry == null) {
entry=new Entry();
connections.put(sender, entry);
if(log.isTraceEnabled())
log.trace(local_addr + ": created new connection for dst " + sender);
}
win=entry.received_msgs;
if(win == null) {
win=new AckReceiverWindow(DEFAULT_FIRST_SEQNO);
entry.received_msgs=win;
}
}
boolean added=win.add(seqno, msg); // entry.received_msgs is guaranteed to be non-null if we get here
boolean regular_msg_added=added && !msg.isFlagSet(Message.OOB);
num_msgs_received++;
num_bytes_received+=msg.getLength();
// http://jira.jboss.com/jira/browse/JGRP-713: // send the ack back *before* we process the message
// to limit unnecessary retransmits
if(immediate_ack)
sendAck(sender, seqno); // send an ack regardless of whether the message was added (stops retransmission)
// message is passed up if OOB. Later, when remove() is called, we discard it. This affects ordering !
// http://jira.jboss.com/jira/browse/JGRP-377
if(msg.isFlagSet(Message.OOB)) {
if(added)
up_prot.up(new Event(Event.MSG, msg));
win.removeOOBMessage(); // if we only have OOB messages, we'd never remove them !
if(!(win.hasMessagesToRemove() && undelivered_msgs.get() > 0))
return true;
}
if(!added && !win.hasMessagesToRemove()) { // no ack if we didn't add the msg (e.g. duplicate)
return true; // ack the message, because this will stop retransmissions (which are unreliable) !
}
// Try to remove (from the AckReceiverWindow) as many messages as possible as pass them up
Message m;
short removed_regular_msgs=0;
// Prevents concurrent passing up of messages by different threads (http://jira.jboss.com/jira/browse/JGRP-198);
// this is all the more important once we have a threadless stack (http://jira.jboss.com/jira/browse/JGRP-181),
// where lots of threads can come up to this point concurrently, but only 1 is allowed to pass at a time
// We *can* deliver messages from *different* senders concurrently, e.g. reception of P1, Q1, P2, Q2 can result in
// delivery of P1, Q1, Q2, P2: FIFO (implemented by UNICAST) says messages need to be delivered only in the
// order in which they were sent by their senders
ReentrantLock lock=win.getLock();
lock.lock(); // we don't block on entry any more (http://jira.jboss.com/jira/browse/JGRP-485)
try {
if(eager_lock_release)
locks.put(Thread.currentThread(), lock);
while((m=win.remove()) != null) {
// discard OOB msg as it has already been delivered (http://jira.jboss.com/jira/browse/JGRP-377)
if(m.isFlagSet(Message.OOB)) {
continue;
}
removed_regular_msgs++;