@ManagedOperation(description="Sends ACKs immediately for entries which are marked as pending (ACK hasn't been sent yet)") public void sendPendingAcks() { for(Map.Entry<Address,ReceiverEntry> entry: recv_table.entrySet()) { Address target=entry.getKey(); // target to send retransmit requests to ReceiverEntry val=entry.getValue(); Table<Message> win=val != null? val.msgs : null; // receiver: send ack for received messages if needed if(win != null && val.sendAck())// sendAck() resets send_ack to false sendAck(target, win.getHighestDeliverable(), val.connId()); } }
/** * Returns a list of missing messages * @param max_msgs If > 0, the max number of missing messages to be returned (oldest first), else no limit * @return A SeqnoList of missing messages, or null if no messages are missing */ public SeqnoList getMissing(int max_msgs) { lock.lock(); try { if(size == 0) return null; long start_seqno=getHighestDeliverable() +1; int capacity=(int)(hr - start_seqno); int max_size=max_msgs > 0? Math.min(max_msgs, capacity) : capacity; if(max_size <= 0) return null; Missing missing=new Missing(start_seqno, max_size); long to=max_size > 0? Math.min(start_seqno + max_size-1, hr-1) : hr-1; forEach(start_seqno, to, missing); return missing.getMissingElements(); } finally { lock.unlock(); } }
entry.update(); if(dont_loopback_set) entry.msgs.purge(entry.msgs.getHighestDeliverable()); break;
sendAck(target, win.getHighestDeliverable(), val.connId());
protected void handleBatchReceived(final ReceiverEntry entry, Address sender, List<LongTuple<Message>> msgs, boolean oob) { if(is_trace) log.trace("%s <-- DATA(%s: %s)", local_addr, sender, printMessageList(msgs)); int batch_size=msgs.size(); Table<Message> win=entry.msgs; // adds all messages to the table, removing messages from 'msgs' which could not be added (already present) boolean added=win.add(msgs, oob, oob? DUMMY_OOB_MSG : null); update(entry, batch_size); if(batch_size >= ack_threshold) sendAck(sender, win.getHighestDeliverable(), entry.connId()); else entry.sendAck(true); // OOB msg is passed up. When removed, we discard it. Affects ordering: http://jira.jboss.com/jira/browse/JGRP-379 if(added && oob) { MessageBatch oob_batch=new MessageBatch(local_addr, sender, null, false, MessageBatch.Mode.OOB, msgs.size()); for(LongTuple<Message> tuple: msgs) oob_batch.add(tuple.getVal2()); deliverBatch(oob_batch); } removeAndDeliver(win, sender); }
/** * Check whether the hashtable contains an entry e for {@code sender} (create if not). If * e.received_msgs is null and {@code first} is true: create a new AckReceiverWindow(seqno) and * add message. Set e.received_msgs to the new window. Else just add the message. */ protected void handleDataReceived(final Address sender, long seqno, short conn_id, boolean first, final Message msg) { ReceiverEntry entry=getReceiverEntry(sender, seqno, first, conn_id); if(entry == null) return; update(entry, 1); boolean oob=msg.isFlagSet(Message.Flag.OOB); final Table<Message> win=entry.msgs; boolean added=win.add(seqno, oob? DUMMY_OOB_MSG : msg); // adding the same dummy OOB msg saves space (we won't remove it) if(ack_threshold <= 1) sendAck(sender, win.getHighestDeliverable(), entry.connId()); else entry.sendAck(true); // will be sent delayed (on the next xmit_interval) // An OOB message is passed up immediately. Later, when remove() is called, we discard it. This affects ordering ! // http://jira.jboss.com/jira/browse/JGRP-377 if(oob) { if(added) deliverMessage(msg, sender, seqno); // we don't steal work if the message is internal (https://issues.jboss.org/browse/JGRP-1733) if(msg.isFlagSet(Message.Flag.INTERNAL)) { processInternalMessage(win, sender); return; } } removeAndDeliver(win, sender); }
@ManagedOperation(description="Sends ACKs immediately for entries which are marked as pending (ACK hasn't been sent yet)") public void sendPendingAcks() { for(Map.Entry<Address,ReceiverEntry> entry: recv_table.entrySet()) { Address target=entry.getKey(); // target to send retransmit requests to ReceiverEntry val=entry.getValue(); Table<Message> win=val != null? val.msgs : null; // receiver: send ack for received messages if needed if(win != null && val.sendAck())// sendAck() resets send_ack to false sendAck(target, win.getHighestDeliverable(), val.connId()); } }
/** * Returns a list of missing messages * @param max_msgs If > 0, the max number of missing messages to be returned (oldest first), else no limit * @return A SeqnoList of missing messages, or null if no messages are missing */ public SeqnoList getMissing(int max_msgs) { lock.lock(); try { if(size == 0) return null; long start_seqno=getHighestDeliverable() +1; int capacity=(int)(hr - start_seqno); int max_size=max_msgs > 0? Math.min(max_msgs, capacity) : capacity; if(max_size <= 0) return null; Missing missing=new Missing(start_seqno, max_size); long to=max_size > 0? Math.min(start_seqno + max_size-1, hr-1) : hr-1; forEach(start_seqno, to, missing); return missing.getMissingElements(); } finally { lock.unlock(); } }
entry.update(); if(dont_loopback_set) entry.msgs.purge(entry.msgs.getHighestDeliverable()); break;
sendAck(target, win.getHighestDeliverable(), val.connId());
protected void handleBatchReceived(final ReceiverEntry entry, Address sender, List<LongTuple<Message>> msgs, boolean oob) { if(is_trace) log.trace("%s <-- DATA(%s: %s)", local_addr, sender, printMessageList(msgs)); int batch_size=msgs.size(); Table<Message> win=entry.msgs; // adds all messages to the table, removing messages from 'msgs' which could not be added (already present) boolean added=win.add(msgs, oob, oob? DUMMY_OOB_MSG : null); update(entry, batch_size); if(batch_size >= ack_threshold) sendAck(sender, win.getHighestDeliverable(), entry.connId()); else entry.sendAck(true); // OOB msg is passed up. When removed, we discard it. Affects ordering: http://jira.jboss.com/jira/browse/JGRP-379 if(added && oob) { MessageBatch oob_batch=new MessageBatch(local_addr, sender, null, false, MessageBatch.Mode.OOB, msgs.size()); for(LongTuple<Message> tuple: msgs) oob_batch.add(tuple.getVal2()); deliverBatch(oob_batch); } removeAndDeliver(win, sender); }
/** * Check whether the hashtable contains an entry e for {@code sender} (create if not). If * e.received_msgs is null and {@code first} is true: create a new AckReceiverWindow(seqno) and * add message. Set e.received_msgs to the new window. Else just add the message. */ protected void handleDataReceived(final Address sender, long seqno, short conn_id, boolean first, final Message msg) { ReceiverEntry entry=getReceiverEntry(sender, seqno, first, conn_id); if(entry == null) return; update(entry, 1); boolean oob=msg.isFlagSet(Message.Flag.OOB); final Table<Message> win=entry.msgs; boolean added=win.add(seqno, oob? DUMMY_OOB_MSG : msg); // adding the same dummy OOB msg saves space (we won't remove it) if(ack_threshold <= 1) sendAck(sender, win.getHighestDeliverable(), entry.connId()); else entry.sendAck(true); // will be sent delayed (on the next xmit_interval) // An OOB message is passed up immediately. Later, when remove() is called, we discard it. This affects ordering ! // http://jira.jboss.com/jira/browse/JGRP-377 if(oob) { if(added) deliverMessage(msg, sender, seqno); // we don't steal work if the message is internal (https://issues.jboss.org/browse/JGRP-1733) if(msg.isFlagSet(Message.Flag.INTERNAL)) { processInternalMessage(win, sender); return; } } removeAndDeliver(win, sender); }