// the packet, only it can't b/c its sentPacket is also full - we got a deadlock.
// as I see it, the only way to truly resolve it is to have multi-part packets, but we don't want to do that.
// what we do is that we don't allow a packet with requests only to be full - we always leave room for a response.
// assumes hasRequests and requestsOnly are up to date.
Message next = overflow;
overflow = null;
if (next == null)
next = queue.poll();
for (;;) {
LOG.trace("handleQueue loop");
if (next == null) {
LOG.trace("handleQueue loop: next == null");
break;
}
overflow = next; // we put the next message into overflow. if we _don't_ break out of the loop and use the message, we'll null overflow
final boolean unicastBroadcast = next.isBroadcast() && unicastBroadcasts.remove(next);
if (broadcast && (!next.isBroadcast() || unicastBroadcast)) {
LOG.trace("Node peer {} not taking non-broadcast message {} during broadcast", this, next);
break; // we're not taking any non-broadcast messages during broadcast
}
if (!broadcast && next.isBroadcast() && !unicastBroadcast) {
if (sentPacket == null || sentPacket.isEmpty()) {
LOG.debug("Node peer {} going into broadcast mode for message {}.", this, next);
broadcast = true;
}
// else, we add message to packet, and continue transmitting.
// if the packet had responses only, the new broadcast request would force a re-send and expedite matters
// if a response for the broadcast is received before we get a chance to multicast, that's ok because we simply remove the node
// from the BroadcastEntry
}
if (next.size() > maxPacketSize) {
LOG.error("Message {} is larger than the maximum packet size {}", next, maxPacketSize);
throw new RuntimeException("Message is larger than maxPacketSize");
}
if (next.size() + sentPacketSizeInBytes() > maxPacketSize) {
if (next.isResponse() && requestsOnly)
LOG.warn("IMPORTANT: Response message {} does not fit in packet {} which contains only requests. THIS MAY CAUSE A DEADLOCK!", next, sentPacket);
LOG.debug("Message {} cannot be added to packet now; packet full.");
break;
}
if (!next.isResponse()) {
if (requestsOnly && next.size() + sentPacketSizeInBytes() > maxRequestOnlyPacketSize && sentPacketSizeInBytes() > 0) {
// check if packet consists of requestOnly message unless it is only one message.
LOG.debug("NOT Sending requests only {}. can't add to packet {} bytes long.", next, sentPacketSizeInBytes());
break;
}
hasRequests = true;
} else
requestsOnly = false;
if (next.isResponse())
pendingRequests.remove(next.getMessageId());
LOG.debug("Adding message {} to sent-packet", next);
if (sentPacket == null)
sentPacket = new MessagePacket();
sentPacket.addMessage(next);